276 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'dart:convert';
 | |
| 
 | |
| import 'package:flutter/material.dart';
 | |
| import 'package:flutter_hbb/models/platform_model.dart';
 | |
| import 'package:get/get.dart';
 | |
| import 'package:scroll_pos/scroll_pos.dart';
 | |
| 
 | |
| import '../common.dart';
 | |
| import 'model.dart';
 | |
| 
 | |
| const int groupTabIndex = 4;
 | |
| const String defaultGroupTabname = 'Group';
 | |
| 
 | |
| class PeerTabModel with ChangeNotifier {
 | |
|   WeakReference<FFI> parent;
 | |
|   int get currentTab => _currentTab;
 | |
|   int _currentTab = 0; // index in tabNames
 | |
|   List<int> get visibleOrderedTabs => _visibleOrderedTabs;
 | |
|   List<int> _visibleOrderedTabs = List.empty(growable: true);
 | |
|   List<int> get tabOrder => _tabOrder;
 | |
|   List<int> _tabOrder = List.from([0, 1, 2, 3, 4]); // constant length
 | |
|   int get tabHiddenFlag => _tabHiddenFlag;
 | |
|   int _tabHiddenFlag = 0;
 | |
|   bool get showScrollBtn => _showScrollBtn;
 | |
|   bool _showScrollBtn = false;
 | |
|   final List<bool> _fullyVisible = List.filled(5, false);
 | |
|   bool get leftFullyVisible => _leftFullyVisible;
 | |
|   bool _leftFullyVisible = false;
 | |
|   bool get rightFullyVisible => _rightFullyVisible;
 | |
|   bool _rightFullyVisible = false;
 | |
|   ScrollPosController sc = ScrollPosController();
 | |
|   List<String> tabNames = [
 | |
|     'Recent Sessions',
 | |
|     'Favorites',
 | |
|     'Discovered',
 | |
|     'Address Book',
 | |
|     defaultGroupTabname,
 | |
|   ];
 | |
| 
 | |
|   PeerTabModel(this.parent) {
 | |
|     // init tabHiddenFlag
 | |
|     _tabHiddenFlag = int.tryParse(
 | |
|             bind.getLocalFlutterConfig(k: 'hidden-peer-card'),
 | |
|             radix: 2) ??
 | |
|         0;
 | |
|     var tabs = _notHiddenTabs();
 | |
|     // remove dynamic tabs
 | |
|     tabs.remove(groupTabIndex);
 | |
|     // init tabOrder
 | |
|     try {
 | |
|       final conf = bind.getLocalFlutterConfig(k: 'peer-tab-order');
 | |
|       if (conf.isNotEmpty) {
 | |
|         final json = jsonDecode(conf);
 | |
|         if (json is List) {
 | |
|           final List<int> list =
 | |
|               json.map((e) => int.tryParse(e.toString()) ?? -1).toList();
 | |
|           if (list.length == _tabOrder.length &&
 | |
|               _tabOrder.every((e) => list.contains(e))) {
 | |
|             _tabOrder = list;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     } catch (e) {
 | |
|       debugPrintStack(label: '$e');
 | |
|     }
 | |
|     // init visibleOrderedTabs
 | |
|     var tempList = _tabOrder.toList();
 | |
|     tempList.removeWhere((e) => !tabs.contains(e));
 | |
|     _visibleOrderedTabs = tempList;
 | |
|     // init currentTab
 | |
|     _currentTab =
 | |
|         int.tryParse(bind.getLocalFlutterConfig(k: 'peer-tab-index')) ?? 0;
 | |
|     if (!tabs.contains(_currentTab)) {
 | |
|       if (tabs.isNotEmpty) {
 | |
|         _currentTab = tabs[0];
 | |
|       } else {
 | |
|         _currentTab = 0;
 | |
|       }
 | |
|     }
 | |
|     sc.itemCount = _visibleOrderedTabs.length;
 | |
|   }
 | |
| 
 | |
|   check_dynamic_tabs() {
 | |
|     var visible = visibleTabs();
 | |
|     _visibleOrderedTabs = _tabOrder.where((e) => visible.contains(e)).toList();
 | |
|     if (_visibleOrderedTabs.contains(groupTabIndex) &&
 | |
|         int.tryParse(bind.getLocalFlutterConfig(k: 'peer-tab-index')) ==
 | |
|             groupTabIndex) {
 | |
|       _currentTab = groupTabIndex;
 | |
|     }
 | |
|     if (gFFI.userModel.isAdmin.isFalse && gFFI.userModel.groupName.isNotEmpty) {
 | |
|       tabNames[groupTabIndex] = gFFI.userModel.groupName.value;
 | |
|     } else {
 | |
|       tabNames[groupTabIndex] = defaultGroupTabname;
 | |
|     }
 | |
|     sc.itemCount = _visibleOrderedTabs.length;
 | |
|     notifyListeners();
 | |
|   }
 | |
| 
 | |
|   setCurrentTab(int index) {
 | |
|     if (_currentTab != index) {
 | |
|       _currentTab = index;
 | |
|       notifyListeners();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   setTabFullyVisible(int index, bool visible) {
 | |
|     if (index >= 0 && index < _fullyVisible.length) {
 | |
|       if (visible != _fullyVisible[index]) {
 | |
|         _fullyVisible[index] = visible;
 | |
|         bool changed = false;
 | |
|         bool show = _visibleOrderedTabs.any((e) => !_fullyVisible[e]);
 | |
|         if (show != _showScrollBtn) {
 | |
|           _showScrollBtn = show;
 | |
|           changed = true;
 | |
|         }
 | |
|         if (_visibleOrderedTabs.isNotEmpty && _visibleOrderedTabs[0] == index) {
 | |
|           if (_leftFullyVisible != visible) {
 | |
|             _leftFullyVisible = visible;
 | |
|             changed = true;
 | |
|           }
 | |
|         }
 | |
|         if (_visibleOrderedTabs.isNotEmpty &&
 | |
|             _visibleOrderedTabs.last == index) {
 | |
|           if (_rightFullyVisible != visible) {
 | |
|             _rightFullyVisible = visible;
 | |
|             changed = true;
 | |
|           }
 | |
|         }
 | |
|         if (changed) {
 | |
|           notifyListeners();
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   onReorder(oldIndex, newIndex) {
 | |
|     if (oldIndex < newIndex) {
 | |
|       newIndex -= 1;
 | |
|     }
 | |
|     var list = _visibleOrderedTabs.toList();
 | |
|     final int item = list.removeAt(oldIndex);
 | |
|     list.insert(newIndex, item);
 | |
|     _visibleOrderedTabs = list;
 | |
| 
 | |
|     var tmpTabOrder = _visibleOrderedTabs.toList();
 | |
|     var left = _tabOrder.where((e) => !tmpTabOrder.contains(e)).toList();
 | |
|     for (var t in left) {
 | |
|       _addTabInOrder(tmpTabOrder, t);
 | |
|     }
 | |
|     _tabOrder = tmpTabOrder;
 | |
|     bind.setLocalFlutterConfig(k: 'peer-tab-order', v: jsonEncode(tmpTabOrder));
 | |
|     notifyListeners();
 | |
|   }
 | |
| 
 | |
|   onHideShow(int index, bool show) async {
 | |
|     int bitMask = 1 << index;
 | |
|     if (show) {
 | |
|       _tabHiddenFlag &= ~bitMask;
 | |
|     } else {
 | |
|       _tabHiddenFlag |= bitMask;
 | |
|     }
 | |
|     await bind.setLocalFlutterConfig(
 | |
|         k: 'hidden-peer-card', v: _tabHiddenFlag.toRadixString(2));
 | |
|     var visible = visibleTabs();
 | |
|     _visibleOrderedTabs = _tabOrder.where((e) => visible.contains(e)).toList();
 | |
|     if (_visibleOrderedTabs.isNotEmpty &&
 | |
|         !_visibleOrderedTabs.contains(_currentTab)) {
 | |
|       _currentTab = _visibleOrderedTabs[0];
 | |
|     }
 | |
|     notifyListeners();
 | |
|   }
 | |
| 
 | |
|   List<int> orderedNotFilteredTabs() {
 | |
|     var list = tabOrder.toList();
 | |
|     if (_filterGroupCard()) {
 | |
|       list.remove(groupTabIndex);
 | |
|     }
 | |
|     return list;
 | |
|   }
 | |
| 
 | |
|   // return index array of tabNames
 | |
|   List<int> visibleTabs() {
 | |
|     var v = List<int>.empty(growable: true);
 | |
|     for (int i = 0; i < tabNames.length; i++) {
 | |
|       if (!_isTabHidden(i) && !_isTabFilter(i)) {
 | |
|         v.add(i);
 | |
|       }
 | |
|     }
 | |
|     return v;
 | |
|   }
 | |
| 
 | |
|   String translatedTabname(int index) {
 | |
|     if (index >= 0 && index < tabNames.length) {
 | |
|       final name = tabNames[index];
 | |
|       if (index == groupTabIndex) {
 | |
|         if (name == defaultGroupTabname) {
 | |
|           return translate(name);
 | |
|         } else {
 | |
|           return name;
 | |
|         }
 | |
|       } else {
 | |
|         return translate(name);
 | |
|       }
 | |
|     }
 | |
|     assert(false);
 | |
|     return index.toString();
 | |
|   }
 | |
| 
 | |
|   bool _isTabHidden(int tabindex) {
 | |
|     return _tabHiddenFlag & (1 << tabindex) != 0;
 | |
|   }
 | |
| 
 | |
|   bool _isTabFilter(int tabIndex) {
 | |
|     if (tabIndex == groupTabIndex) {
 | |
|       return _filterGroupCard();
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // return true if hide group card
 | |
|   bool _filterGroupCard() {
 | |
|     if (gFFI.groupModel.users.isEmpty ||
 | |
|         (gFFI.userModel.isAdmin.isFalse && gFFI.userModel.groupName.isEmpty)) {
 | |
|       return true;
 | |
|     } else {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   List<int> _notHiddenTabs() {
 | |
|     var v = List<int>.empty(growable: true);
 | |
|     for (int i = 0; i < tabNames.length; i++) {
 | |
|       if (!_isTabHidden(i)) {
 | |
|         v.add(i);
 | |
|       }
 | |
|     }
 | |
|     return v;
 | |
|   }
 | |
| 
 | |
|   // add tabIndex to list
 | |
|   _addTabInOrder(List<int> list, int tabIndex) {
 | |
|     if (!_tabOrder.contains(tabIndex) || list.contains(tabIndex)) {
 | |
|       return;
 | |
|     }
 | |
|     bool sameOrder = true;
 | |
|     int lastIndex = -1;
 | |
|     for (int i = 0; i < list.length; i++) {
 | |
|       var index = _tabOrder.lastIndexOf(list[i]);
 | |
|       if (index > lastIndex) {
 | |
|         lastIndex = index;
 | |
|         continue;
 | |
|       } else {
 | |
|         sameOrder = false;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (sameOrder) {
 | |
|       var indexInTabOrder = _tabOrder.indexOf(tabIndex);
 | |
|       var left = List.empty(growable: true);
 | |
|       for (int i = 0; i < indexInTabOrder; i++) {
 | |
|         left.add(_tabOrder[i]);
 | |
|       }
 | |
|       int insertIndex = list.lastIndexWhere((e) => left.contains(e));
 | |
|       if (insertIndex < 0) {
 | |
|         insertIndex = 0;
 | |
|       } else {
 | |
|         insertIndex += 1;
 | |
|       }
 | |
|       list.insert(insertIndex, tabIndex);
 | |
|     } else {
 | |
|       list.add(tabIndex);
 | |
|     }
 | |
|   }
 | |
| }
 |