Skip to content

Commit 8ad8918

Browse files
Support slide options;remove tile layout
1 parent 8b4944b commit 8ad8918

37 files changed

+4154
-49
lines changed

lib/Resources/theme_color_data.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class ThemeColorData {
120120
dividerColor: const Color(0xFFF5F5F5),
121121
tagBackground: const Color(0xFFF5F5F5),
122122
tagColor: const Color(0xFFBDBDBD),
123-
cardBackground: const Color(0xFFF5F5F5),
123+
cardBackground: const Color(0x119E9E9E),
124124
),
125125
ThemeColorData(
126126
id: "freshGreen",

lib/Screens/Setting/setting_operation_screen.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class _OperationSettingScreenState extends State<OperationSettingScreen>
2424
bool clipToCopy = HiveUtil.getBool(HiveUtil.clickToCopyKey);
2525
bool autoCopyNextCode = HiveUtil.getBool(HiveUtil.autoCopyNextCodeKey);
2626
bool autoDisplayNextCode = HiveUtil.getBool(HiveUtil.autoDisplayNextCodeKey);
27+
bool autoFocusSearchBar = HiveUtil.getBool(HiveUtil.autoFocusSearchBarKey,defaultValue: false);
2728
bool autoMinimizeAfterClickToCopy = HiveUtil.getBool(
2829
HiveUtil.autoMinimizeAfterClickToCopyKey,
2930
defaultValue: false);
@@ -208,6 +209,21 @@ class _OperationSettingScreenState extends State<OperationSettingScreen>
208209
);
209210
},
210211
),
212+
const SizedBox(height: 10),
213+
ItemBuilder.buildRadioItem(
214+
context: context,
215+
value: autoFocusSearchBar,
216+
title: S.current.autoFocusSearchBar,
217+
description: S.current.autoFocusSearchBarTip,
218+
topRadius: true,
219+
bottomRadius: true,
220+
onTap: () {
221+
setState(() {
222+
autoFocusSearchBar = !autoFocusSearchBar;
223+
HiveUtil.put(HiveUtil.autoFocusSearchBarKey, autoFocusSearchBar);
224+
});
225+
},
226+
),
211227
];
212228
}
213229
}

lib/Screens/Token/import_export_token_screen.dart

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -276,26 +276,6 @@ class _ImportExportTokenScreenState extends State<ImportExportTokenScreen>
276276
}
277277
},
278278
),
279-
ItemBuilder.buildEntryItem(
280-
context: context,
281-
title: S.current.exportQrcode,
282-
description: S.current.exportQrcodeHint,
283-
onTap: () async {
284-
List<String>? qrCodes = await ExportTokenUtil.exportToQrcodes();
285-
if (qrCodes != null && qrCodes.isNotEmpty) {
286-
DialogBuilder.showQrcodesDialog(
287-
context,
288-
title: S.current.exportQrcode,
289-
message: S.current.exportQrcodeMessage,
290-
qrcodes: qrCodes,
291-
);
292-
} else if (qrCodes != null && qrCodes.isEmpty) {
293-
IToast.showTop(S.current.exportQrcodeNoData);
294-
} else {
295-
IToast.showTop(S.current.exportFailed);
296-
}
297-
},
298-
),
299279
ItemBuilder.buildEntryItem(
300280
context: context,
301281
title: S.current.exportUriFile,
@@ -325,6 +305,26 @@ class _ImportExportTokenScreenState extends State<ImportExportTokenScreen>
325305
);
326306
},
327307
),
308+
ItemBuilder.buildEntryItem(
309+
context: context,
310+
title: S.current.exportQrcode,
311+
description: S.current.exportQrcodeHint,
312+
onTap: () async {
313+
List<String>? qrCodes = await ExportTokenUtil.exportToQrcodes();
314+
if (qrCodes != null && qrCodes.isNotEmpty) {
315+
DialogBuilder.showQrcodesDialog(
316+
context,
317+
title: S.current.exportQrcode,
318+
message: S.current.exportQrcodeMessage,
319+
qrcodes: qrCodes,
320+
);
321+
} else if (qrCodes != null && qrCodes.isEmpty) {
322+
IToast.showTop(S.current.exportQrcodeNoData);
323+
} else {
324+
IToast.showTop(S.current.exportFailed);
325+
}
326+
},
327+
),
328328
// const SizedBox(height: 10),
329329
// ItemBuilder.buildCaptionItem(
330330
// context: context, title: S.current.exportToThirdParty),

lib/Screens/Token/token_layout.dart

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:cloudotp/Widgets/Item/item_builder.dart';
1616
import 'package:context_menus/context_menus.dart';
1717
import 'package:flutter/material.dart';
1818
import 'package:flutter/services.dart';
19+
import 'package:flutter_slidable/flutter_slidable.dart';
1920
import 'package:move_to_background/move_to_background.dart';
2021
import 'package:provider/provider.dart';
2122
import 'package:window_manager/window_manager.dart';
@@ -204,18 +205,122 @@ class TokenLayoutState extends State<TokenLayout>
204205
);
205206
}
206207

208+
_buildSlidable({
209+
required Widget child,
210+
bool simple = false,
211+
double startExtentRatio = 0.16,
212+
double endExtentRatio = 0.64,
213+
}) {
214+
return Slidable(
215+
groupTag: "TokenLayout",
216+
enabled: !ResponsiveUtil.isWideLandscape(),
217+
startActionPane: ActionPane(
218+
extentRatio: startExtentRatio,
219+
motion: const ScrollMotion(),
220+
children: [
221+
SlidableAction(
222+
onPressed: (context) => _processPin(),
223+
backgroundColor: widget.token.pinned
224+
? Theme.of(context).primaryColor
225+
: Theme.of(context).cardColor,
226+
borderRadius: const BorderRadius.all(Radius.circular(12)),
227+
foregroundColor: Theme.of(context).primaryColor,
228+
icon: widget.token.pinned
229+
? Icons.push_pin_rounded
230+
: Icons.push_pin_outlined,
231+
label: widget.token.pinned
232+
? S.current.unPinTokenShort
233+
: S.current.pinTokenShort,
234+
simple: simple,
235+
spacing: 8,
236+
padding: const EdgeInsets.symmetric(horizontal: 4),
237+
iconAndTextColor: widget.token.pinned ? Colors.white : null,
238+
),
239+
const SizedBox(width: 6),
240+
],
241+
),
242+
endActionPane: ActionPane(
243+
extentRatio: endExtentRatio,
244+
motion: const ScrollMotion(),
245+
children: [
246+
const SizedBox(width: 6),
247+
SlidableAction(
248+
onPressed: (context) => _processViewQrCode(),
249+
backgroundColor: Theme.of(context).cardColor,
250+
borderRadius: const BorderRadius.all(Radius.circular(12)),
251+
foregroundColor: Theme.of(context).primaryColor,
252+
icon: Icons.qr_code_rounded,
253+
label: S.current.viewTokenQrCodeShort,
254+
spacing: 8,
255+
simple: simple,
256+
padding: const EdgeInsets.symmetric(horizontal: 4),
257+
),
258+
const SizedBox(width: 6),
259+
SlidableAction(
260+
onPressed: (context) => _processEdit(),
261+
backgroundColor: Theme.of(context).cardColor,
262+
borderRadius: const BorderRadius.all(Radius.circular(12)),
263+
foregroundColor: Theme.of(context).primaryColor,
264+
icon: Icons.edit_outlined,
265+
padding: const EdgeInsets.symmetric(horizontal: 4),
266+
label: S.current.editTokenShort,
267+
simple: simple,
268+
spacing: 8,
269+
),
270+
const SizedBox(width: 6),
271+
SlidableAction(
272+
onPressed: (context) => showContextMenu(),
273+
backgroundColor: Theme.of(context).cardColor,
274+
borderRadius: const BorderRadius.all(Radius.circular(12)),
275+
foregroundColor: Theme.of(context).primaryColor,
276+
icon: Icons.more_vert_rounded,
277+
padding: const EdgeInsets.symmetric(horizontal: 4),
278+
label: S.current.moreOptionShort,
279+
simple: simple,
280+
spacing: 8,
281+
),
282+
const SizedBox(width: 6),
283+
SlidableAction(
284+
onPressed: (context) => _processDelete(),
285+
backgroundColor: Colors.red,
286+
borderRadius: const BorderRadius.all(Radius.circular(12)),
287+
foregroundColor: Theme.of(context).primaryColor,
288+
icon: Icons.delete,
289+
simple: simple,
290+
label: S.current.deleteTokenShort,
291+
padding: const EdgeInsets.symmetric(horizontal: 4),
292+
spacing: 8,
293+
iconAndTextColor: Colors.white,
294+
),
295+
],
296+
),
297+
child: child,
298+
);
299+
}
300+
207301
_buildBody() {
208302
switch (widget.layoutType) {
209303
case LayoutType.Simple:
210304
return _buildSimpleLayout();
211305
case LayoutType.Compact:
212306
return _buildCompactLayout();
213-
case LayoutType.Tile:
214-
return _buildTileLayout();
307+
// case LayoutType.Tile:
308+
// return _buildSlidable(
309+
// startExtentRatio: 0.23,
310+
// endExtentRatio: 0.9,
311+
// child: _buildTileLayout(),
312+
// );
215313
case LayoutType.List:
216-
return _buildListLayout();
314+
return _buildSlidable(
315+
simple: true,
316+
child: _buildListLayout(),
317+
);
217318
case LayoutType.Spotlight:
218-
return _buildSpotlightLayout();
319+
return _buildSlidable(
320+
startExtentRatio: 0.21,
321+
endExtentRatio: 0.8,
322+
child: _buildSpotlightLayout(),
323+
);
219324
}
220325
}
221326

lib/Screens/home_screen.dart

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'package:cloudotp/Widgets/Item/item_builder.dart';
1717
import 'package:context_menus/context_menus.dart';
1818
import 'package:flutter/material.dart';
1919
import 'package:flutter/services.dart';
20+
import 'package:flutter_slidable/flutter_slidable.dart';
2021
import 'package:move_to_background/move_to_background.dart';
2122
import 'package:package_info_plus/package_info_plus.dart';
2223
import 'package:provider/provider.dart';
@@ -104,6 +105,13 @@ class HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
104105
value: 1,
105106
duration: const Duration(milliseconds: 300),
106107
);
108+
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
109+
if (!ResponsiveUtil.isLandscape() &&
110+
HiveUtil.getBool(HiveUtil.autoFocusSearchBarKey,
111+
defaultValue: false)) {
112+
changeSearchBar(true);
113+
}
114+
});
107115
}
108116

109117
initAppName() {
@@ -754,7 +762,7 @@ class HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
754762
],
755763
)
756764
: gridView;
757-
return body;
765+
return SlidableAutoCloseBehavior(child:body);
758766
}
759767

760768
_buildTabBar([EdgeInsetsGeometry? padding]) {
@@ -1067,18 +1075,17 @@ class HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
10671075
enum LayoutType {
10681076
Simple,
10691077
Compact,
1070-
Tile,
1071-
List,
1072-
Spotlight;
1078+
Spotlight,
1079+
List;
10731080

10741081
double get maxCrossAxisExtent {
10751082
switch (this) {
10761083
case LayoutType.Simple:
10771084
return 250;
10781085
case LayoutType.Compact:
10791086
return 250;
1080-
case LayoutType.Tile:
1081-
return 420;
1087+
// case LayoutType.Tile:
1088+
// return 420;
10821089
case LayoutType.List:
10831090
return 480;
10841091
case LayoutType.Spotlight:
@@ -1092,8 +1099,8 @@ enum LayoutType {
10921099
return 108;
10931100
case LayoutType.Compact:
10941101
return 108;
1095-
case LayoutType.Tile:
1096-
return 114;
1102+
// case LayoutType.Tile:
1103+
// return 114;
10971104
case LayoutType.List:
10981105
return 60;
10991106
case LayoutType.Spotlight:

lib/Screens/main_screen.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import '../Utils/itoast.dart';
4141
import '../Utils/lottie_util.dart';
4242
import '../Utils/route_util.dart';
4343
import '../Utils/utils.dart';
44-
import '../Widgets/BottomSheet/bottom_sheet_builder.dart';
4544
import '../Widgets/BottomSheet/import_from_third_party_bottom_sheet.dart';
4645
import '../Widgets/Custom/loading_icon.dart';
4746
import '../Widgets/Dialog/custom_dialog.dart';
@@ -185,6 +184,10 @@ class MainScreenState extends State<MainScreen>
185184
autoForward: !Utils.isDark(context),
186185
controller: darkModeController,
187186
);
187+
if (HiveUtil.getBool(HiveUtil.autoFocusSearchBarKey,
188+
defaultValue: false)) {
189+
searchFocusNode.requestFocus();
190+
}
188191
});
189192
initGlobalConfig();
190193
searchController.addListener(() {
@@ -432,13 +435,13 @@ class MainScreenState extends State<MainScreen>
432435
homeScreenState?.changeLayoutType(LayoutType.Compact);
433436
},
434437
),
435-
ContextMenuButtonConfig.checkbox(
436-
S.current.tileLayoutType,
437-
checked: homeScreenState?.layoutType == LayoutType.Tile,
438-
onPressed: () {
439-
homeScreenState?.changeLayoutType(LayoutType.Tile);
440-
},
441-
),
438+
// ContextMenuButtonConfig.checkbox(
439+
// S.current.tileLayoutType,
440+
// checked: homeScreenState?.layoutType == LayoutType.Tile,
441+
// onPressed: () {
442+
// homeScreenState?.changeLayoutType(LayoutType.Tile);
443+
// },
444+
// ),
442445
ContextMenuButtonConfig.checkbox(
443446
S.current.listLayoutType,
444447
checked: homeScreenState?.layoutType == LayoutType.List,

lib/TokenUtils/import_token_util.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:cloudotp/Database/token_dao.dart';
55
import 'package:cloudotp/Models/opt_token.dart';
66
import 'package:cloudotp/TokenUtils/Backup/backup_encrypt_old.dart';
77
import 'package:cloudotp/TokenUtils/otp_token_parser.dart';
8+
import 'package:cloudotp/TokenUtils/token_image_util.dart';
89
import 'package:cloudotp/Utils/app_provider.dart';
910
import 'package:cloudotp/Utils/itoast.dart';
1011
import 'package:cloudotp/Utils/responsive_util.dart';
@@ -648,6 +649,8 @@ class ImportTokenUtil {
648649
List<OtpToken> already = await TokenDao.listTokens();
649650
List<OtpToken> newTokenList = [];
650651
for (OtpToken otpToken in tokenList) {
652+
if (otpToken.issuer.isEmpty) otpToken.issuer = otpToken.account;
653+
otpToken.imagePath = TokenImageUtil.matchBrandLogo(otpToken) ?? "";
651654
OtpToken? alreadyToken = checkTokenExist(otpToken, already);
652655
if (alreadyToken == null &&
653656
checkTokenExist(otpToken, newTokenList) == null) {

lib/Utils/hive_util.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class HiveUtil {
4545
static const String inappWebviewKey = "inappWebview";
4646

4747
static const String clickToCopyKey = "clickToCopy";
48+
static const String autoFocusSearchBarKey = "autoFocusSearchBar";
4849
static const String autoCopyNextCodeKey = "autoCopyNextCode";
4950
static const String autoDisplayNextCodeKey = "autoDisplayNextCode";
5051
static const String autoMinimizeAfterClickToCopyKey =
@@ -108,6 +109,7 @@ class HiveUtil {
108109
await HiveUtil.put(HiveUtil.inappWebviewKey, true);
109110
await HiveUtil.put(HiveUtil.layoutTypeKey, LayoutType.Compact.index);
110111
await HiveUtil.put(HiveUtil.enableSafeModeKey, true);
112+
await HiveUtil.put(HiveUtil.autoFocusSearchBarKey, false);
111113
await HiveUtil.put(HiveUtil.maxBackupsCountKey, defaultMaxBackupCount);
112114
await HiveUtil.put(HiveUtil.backupPathKey, await FileUtil.getBackupDir());
113115
await HiveUtil.put(HiveUtil.dragToReorderKey, !ResponsiveUtil.isMobile());

lib/Widgets/BottomSheet/import_from_third_party_bottom_sheet.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ class ImportFromThirdPartyBottomSheetState
5757
.titleMedium
5858
?.apply(fontWeightDelta: 2),
5959
),
60-
center: !ResponsiveUtil.isLandscape(),
6160
actions: ResponsiveUtil.isLandscape()
6261
? []
6362
: [
@@ -226,6 +225,12 @@ class ImportFromThirdPartyBottomSheetState
226225
Function(String)? onImport,
227226
bool useImport = true,
228227
}) {
228+
final allowedExtensionsInAndroid = ['txt', 'json', 'zip'];
229+
bool containUnsupportExt = false;
230+
for (var ext in allowedExtensions) {
231+
if (!allowedExtensionsInAndroid.contains(ext)) containUnsupportExt = true;
232+
}
233+
containUnsupportExt = containUnsupportExt && ResponsiveUtil.isAndroid();
229234
return Material(
230235
color: Theme.of(context).canvasColor,
231236
borderRadius: BorderRadius.circular(10),
@@ -234,8 +239,9 @@ class ImportFromThirdPartyBottomSheetState
234239
? () async {
235240
FilePickerResult? result = await FileUtil.pickFiles(
236241
dialogTitle: dialogTitle,
237-
type: FileType.custom,
238-
allowedExtensions: allowedExtensions,
242+
type: containUnsupportExt ? FileType.any : FileType.custom,
243+
allowedExtensions:
244+
containUnsupportExt ? [] : allowedExtensions,
239245
lockParentWindow: true,
240246
);
241247
if (result != null) {

0 commit comments

Comments
 (0)