Skip to content

Commit 10e03d2

Browse files
committed
feat: update home pagr
1 parent 113908a commit 10e03d2

29 files changed

Lines changed: 1005 additions & 918 deletions
File renamed without changes.

lib/l10n/app_en.arb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"sort": "Sort",
9797
"source_code": "Source code",
9898
"storage": "Storage",
99+
"storages": "Storages",
99100
"stretch": "Stretch",
100101
"subtitle": "Subtitle",
101102
"subtitle_and_audio_track": "Subtitle and audio track",

lib/l10n/app_zh.arb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"sort": "排序",
9797
"source_code": "源码",
9898
"storage": "存储",
99+
"storages": "存储",
99100
"stretch": "拉伸",
100101
"subtitle": "字幕",
101102
"subtitle_and_audio_track": "字幕和音轨",

lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:fvp/fvp.dart' as fvp;
44
import 'package:flutter/material.dart';
55
import 'package:flutter_hooks/flutter_hooks.dart';
66
import 'package:flutter_zustand/flutter_zustand.dart';
7-
import 'package:iris/info.dart';
7+
import 'package:iris/data/info.dart';
88
import 'package:iris/l10n/app_localizations.dart';
99
import 'package:iris/models/file.dart';
1010
import 'package:iris/pages/home/home.dart';

lib/models/storages/storage.dart

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import 'package:iris/models/file.dart';
55
import 'package:iris/models/storages/ftp.dart';
66
import 'package:iris/models/storages/local.dart';
77
import 'package:iris/models/storages/webdav.dart';
8+
import 'package:iris/store/use_ui_store.dart';
89
import 'package:iris/utils/platform.dart';
9-
import 'package:iris/widgets/iris_popup.dart';
10-
import 'package:iris/pages/storages/storages.dart';
1110
import 'package:iris/store/use_storage_store.dart';
1211

1312
part 'storage.freezed.dart';
@@ -140,11 +139,5 @@ Future<void> openInFolder(BuildContext context, FileItem file) async {
140139
}
141140
}
142141

143-
if (context.mounted) {
144-
replacePopup(
145-
context: context,
146-
child: Storages(),
147-
direction: PopupDirection.right,
148-
);
149-
}
142+
useUiStore().updatePlayerExpanded(false);
150143
}

lib/pages/home/history.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'dart:math';
22

3-
import 'package:flutter/material.dart';
3+
import 'package:flutter/material.dart' hide Chip;
44
import 'package:flutter_hooks/flutter_hooks.dart';
55
import 'package:flutter_zustand/flutter_zustand.dart';
66
import 'package:iris/models/file.dart';
@@ -11,7 +11,7 @@ import 'package:iris/store/use_history_store.dart';
1111
import 'package:iris/store/use_play_queue_store.dart';
1212
import 'package:iris/utils/file_size_convert.dart';
1313
import 'package:iris/utils/get_localizations.dart';
14-
import 'package:iris/widgets/iris_chip.dart';
14+
import 'package:iris/widgets/chip.dart';
1515
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
1616

1717
class History extends HookWidget {
@@ -84,14 +84,14 @@ class History extends HookWidget {
8484
if ((progress.duration.inMilliseconds -
8585
progress.position.inMilliseconds) <=
8686
5000) {
87-
return IRISChip(text: '100%');
87+
return Chip(text: '100%');
8888
}
8989
final String progressString =
9090
(progress.position.inMilliseconds /
9191
progress.duration.inMilliseconds *
9292
100)
9393
.toStringAsFixed(0);
94-
return IRISChip(text: '$progressString %');
94+
return Chip(text: '$progressString %');
9595
} else {
9696
return const SizedBox();
9797
}
@@ -109,7 +109,7 @@ class History extends HookWidget {
109109
mainAxisSize: MainAxisSize.min,
110110
children: [
111111
const SizedBox(width: 4),
112-
IRISChip(
112+
Chip(
113113
text: subtitleType,
114114
primary: true,
115115
),

lib/pages/home/home.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import 'package:flutter_zustand/flutter_zustand.dart';
55
import 'package:iris/hooks/use_fvp_player.dart';
66
import 'package:iris/hooks/use_media_kit_player.dart';
77
import 'package:iris/models/store/app_state.dart';
8+
import 'package:iris/pages/library/library.dart';
89
import 'package:iris/pages/player/iris_player.dart';
9-
import 'package:iris/pages/storages/storages.dart';
1010
import 'package:iris/store/use_app_store.dart';
1111
import 'package:iris/store/use_ui_store.dart';
1212

@@ -60,7 +60,7 @@ class Home extends HookWidget {
6060
top: 0,
6161
right: 0,
6262
bottom: 0,
63-
child: Storages(),
63+
child: Library(),
6464
),
6565
player,
6666
],

lib/pages/library/favorites.dart

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import 'package:collection/collection.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_hooks/flutter_hooks.dart';
4+
import 'package:flutter_zustand/flutter_zustand.dart';
5+
import 'package:iris/models/storages/local.dart';
6+
import 'package:iris/models/storages/storage.dart';
7+
import 'package:iris/models/store/storage_state.dart';
8+
import 'package:iris/store/use_storage_store.dart';
9+
import 'package:iris/utils/get_localizations.dart';
10+
import 'package:path/path.dart' as p;
11+
12+
class Favorites extends HookWidget {
13+
const Favorites({super.key});
14+
15+
@override
16+
Widget build(BuildContext context) {
17+
final t = getLocalizations(context);
18+
19+
final favorites =
20+
useStorageStore().select(context, (state) => state.favorites);
21+
22+
final localStoragesFuture =
23+
useMemoized(() async => await getLocalStorages(context), []);
24+
final localStorages = useFuture(localStoragesFuture).data ?? [];
25+
26+
return favorites.isEmpty
27+
? const SizedBox()
28+
: Column(
29+
children: [
30+
Container(
31+
alignment: Alignment.centerLeft,
32+
padding: const EdgeInsets.symmetric(horizontal: 16),
33+
child: Text(
34+
t.favorites,
35+
style: TextStyle(fontSize: 20),
36+
),
37+
),
38+
GridView.builder(
39+
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
40+
maxCrossAxisExtent: 200,
41+
mainAxisExtent: 140,
42+
mainAxisSpacing: 8,
43+
crossAxisSpacing: 8,
44+
),
45+
shrinkWrap: true,
46+
padding: const EdgeInsets.all(16),
47+
itemCount: favorites.length,
48+
itemBuilder: (context, index) {
49+
final favorite = favorites[index];
50+
return _FavoriteCard(
51+
favorite: favorite,
52+
localStorages: localStorages,
53+
);
54+
},
55+
),
56+
],
57+
);
58+
}
59+
}
60+
61+
class _FavoriteCard extends HookWidget {
62+
final Favorite favorite;
63+
final List<LocalStorage> localStorages;
64+
65+
const _FavoriteCard({
66+
required this.favorite,
67+
required this.localStorages,
68+
});
69+
70+
String _getSubtitle(BuildContext context) {
71+
Storage? storage = useStorageStore().findById(favorite.storageId);
72+
if (storage == null && favorite.storageId == localStorageId) {
73+
storage = localStorages.firstWhereOrNull(
74+
(element) => element.basePath[0] == favorite.path[0]);
75+
}
76+
if (storage == null) return '';
77+
78+
if (storage is LocalStorage) {
79+
final subtitle = p.normalize(favorite.path.join('/'));
80+
if (favorite.path.last == subtitle) {
81+
return '';
82+
}
83+
return subtitle;
84+
} else if (storage is WebDAVStorage) {
85+
return 'http${storage.https ? 's' : ''}://${storage.host}${favorite.path.join('/')}';
86+
} else if (storage is FTPStorage) {
87+
return 'ftp://${storage.username.isNotEmpty ? '${storage.username}@' : ''}${storage.host}:${storage.port}${favorite.path.join('/').replaceFirst('//', '/')}';
88+
} else {
89+
return '';
90+
}
91+
}
92+
93+
@override
94+
Widget build(BuildContext context) {
95+
final t = getLocalizations(context);
96+
final subtitle = _getSubtitle(context);
97+
98+
return Card(
99+
clipBehavior: Clip.hardEdge,
100+
child: InkWell(
101+
onTap: () {
102+
Storage? storage = useStorageStore().findById(favorite.storageId);
103+
if (storage == null && favorite.storageId == localStorageId) {
104+
storage = localStorages.firstWhereOrNull(
105+
(element) => element.basePath[0] == favorite.path[0]);
106+
}
107+
if (storage == null) return;
108+
useStorageStore().updateCurrentPath(favorite.path);
109+
useStorageStore().updateCurrentStorage(storage);
110+
},
111+
child: Padding(
112+
padding: const EdgeInsets.all(12.0),
113+
child: Column(
114+
crossAxisAlignment: CrossAxisAlignment.start,
115+
children: [
116+
Row(
117+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
118+
children: [
119+
Icon(
120+
Icons.star_rounded,
121+
size: 32,
122+
color: Theme.of(context).colorScheme.primary,
123+
),
124+
SizedBox(
125+
width: 40,
126+
height: 40,
127+
child: PopupMenuButton<StorageOptions>(
128+
tooltip: t.menu,
129+
icon: const Icon(Icons.more_vert_rounded),
130+
clipBehavior: Clip.hardEdge,
131+
color:
132+
Theme.of(context).colorScheme.surface.withAlpha(250),
133+
onSelected: (value) {
134+
switch (value) {
135+
case StorageOptions.remove:
136+
useStorageStore().removeFavorite(favorite);
137+
break;
138+
default:
139+
break;
140+
}
141+
},
142+
itemBuilder: (BuildContext context) => [
143+
PopupMenuItem(
144+
value: StorageOptions.remove,
145+
child: Text(t.remove),
146+
),
147+
],
148+
),
149+
),
150+
],
151+
),
152+
const Spacer(),
153+
Text(
154+
favorite.path.last,
155+
style: Theme.of(context).textTheme.titleMedium,
156+
maxLines: 1,
157+
overflow: TextOverflow.ellipsis,
158+
),
159+
if (subtitle.isNotEmpty)
160+
Text(
161+
subtitle,
162+
style: Theme.of(context).textTheme.bodySmall,
163+
maxLines: 1,
164+
overflow: TextOverflow.ellipsis,
165+
),
166+
],
167+
),
168+
),
169+
),
170+
);
171+
}
172+
}
173+
174+
enum StorageOptions {
175+
edit,
176+
remove,
177+
}

0 commit comments

Comments
 (0)