Skip to content

Commit

Permalink
allow tab without account
Browse files Browse the repository at this point in the history
  • Loading branch information
poppingmoon committed Jan 2, 2024
1 parent f249f32 commit 25eaaa3
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 106 deletions.
16 changes: 8 additions & 8 deletions lib/repository/emoji_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import 'package:shared_preferences/shared_preferences.dart';

abstract class EmojiRepository {
List<EmojiRepositoryData>? emoji;
Future<void> loadFromSourceIfNeed();
Future<void> loadFromSource();
Future<void> loadFromSourceIfNeed({bool forceSave = false});
Future<void> loadFromSource({bool forceSave = false});

Future<void> loadFromLocalCache();
Future<List<MisskeyEmojiData>> searchEmojis(String name, {int limit = 30});
Expand Down Expand Up @@ -71,11 +71,11 @@ class EmojiRepositoryImpl extends EmojiRepository {
}

@override
Future<void> loadFromSource() async {
Future<void> loadFromSource({bool forceSave = false}) async {
final serverFetchData = await misskey.emojis();
await _setEmojiData(serverFetchData);

if (account.token != null) {
if (forceSave || account.token != null) {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(
"emojis@${account.host}",
Expand All @@ -91,18 +91,18 @@ class EmojiRepositoryImpl extends EmojiRepository {
}

@override
Future<void> loadFromSourceIfNeed() async {
Future<void> loadFromSourceIfNeed({bool forceSave = false}) async {
final settings = accountSettingsRepository.fromAccount(account);
final latestUpdated = settings.latestEmojiCached;
switch (settings.emojiCacheStrategy) {
case CacheStrategy.whenTabChange:
await loadFromSource();
await loadFromSource(forceSave: forceSave);
case CacheStrategy.whenLaunch:
if (thisLaunchLoaded) return;
await loadFromSource();
await loadFromSource(forceSave: forceSave);
case CacheStrategy.whenOneDay:
if (latestUpdated == null || latestUpdated.day != DateTime.now().day) {
await loadFromSource();
await loadFromSource(forceSave: forceSave);
}
}
}
Expand Down
10 changes: 3 additions & 7 deletions lib/repository/import_export_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,10 @@ class ImportExportRepository extends ChangeNotifier {
final tabSettings = <TabSetting>[];

for (final tabSetting in importedSettings.tabSettings) {
final account = accounts
.firstWhereOrNull((account) => tabSetting.acct == account.acct);

if (account == null) {
continue;
if (tabSetting.acct.username.isEmpty ||
accounts.any((account) => account.acct == tabSetting.acct)) {
tabSettings.add(tabSetting);
}

tabSettings.add(tabSetting);
}
reader(tabSettingsRepositoryProvider).save(tabSettings);

Expand Down
8 changes: 6 additions & 2 deletions lib/repository/timeline_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class TimelineRepository extends FamilyNotifier<TimelineState, TabSetting> {

TabSetting get _tabSetting => arg;

Account get _account => ref.read(accountProvider(_tabSetting.acct));
Account get _account => _tabSetting.acct.username.isEmpty
? Account.demoAccount(_tabSetting.acct.host, null)
: ref.read(accountProvider(_tabSetting.acct));

Misskey get _misskey => ref.read(misskeyProvider(_account));

Expand Down Expand Up @@ -235,7 +237,9 @@ class TimelineRepository extends FamilyNotifier<TimelineState, TabSetting> {
.loadFromSourceIfNeed(_tabSetting.acct);
await Future.wait([
ref.read(mainStreamRepositoryProvider(_account)).reconnect(),
ref.read(emojiRepositoryProvider(_account)).loadFromSourceIfNeed(),
ref
.read(emojiRepositoryProvider(_account))
.loadFromSourceIfNeed(forceSave: true),
if (state.olderNotes.isEmpty)
downDirectionLoad()
else
Expand Down
1 change: 1 addition & 0 deletions lib/view/channels_page/community_channel_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class CommunityChannelView extends StatelessWidget {
child: Image.network(
channel.bannerUrl!.toString(),
fit: BoxFit.fitWidth,
errorBuilder: (_, __, ___) => const SizedBox.shrink(),
),
),
Padding(
Expand Down
4 changes: 2 additions & 2 deletions lib/view/common/misskey_notes/misskey_note.dart
Original file line number Diff line number Diff line change
Expand Up @@ -751,8 +751,8 @@ class NoteHeader1 extends ConsumerWidget {
padding: const EdgeInsets.only(top: 2),
child: GestureDetector(
onTap: () => context.pushRoute(
NoteDetailRoute(
note: displayNote,
UserRoute(
user: displayNote.user,
account: account,
),
),
Expand Down
36 changes: 20 additions & 16 deletions lib/view/settings_page/tab_settings_page/channel_select_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class ChannelSelectDialog extends StatelessWidget {
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.height * 0.8,
child: DefaultTabController(
length: 4,
initialIndex: 2,
length: 2 + (account.hasToken ? 2 : 0),
initialIndex: account.hasToken ? 2 : 0,
child: Column(
children: [
Padding(
Expand All @@ -36,8 +36,10 @@ class ChannelSelectDialog extends StatelessWidget {
tabs: [
Tab(text: S.of(context).search),
Tab(text: S.of(context).trend),
Tab(text: S.of(context).favorite),
Tab(text: S.of(context).following),
if (account.hasToken) ...[
Tab(text: S.of(context).favorite),
Tab(text: S.of(context).following),
],
],
isScrollable: true,
tabAlignment: TabAlignment.center,
Expand All @@ -64,20 +66,22 @@ class ChannelSelectDialog extends StatelessWidget {
Navigator.of(context).pop(channel),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: ChannelFavorited(
onChannelSelected: (channel) =>
Navigator.of(context).pop(channel),
if (account.hasToken) ...[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: ChannelFavorited(
onChannelSelected: (channel) =>
Navigator.of(context).pop(channel),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: ChannelFollowed(
onChannelSelected: (channel) =>
Navigator.of(context).pop(channel),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: ChannelFollowed(
onChannelSelected: (channel) =>
Navigator.of(context).pop(channel),
),
),
),
],
],
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:miria/model/account.dart';
import 'package:miria/model/tab_setting.dart';
import 'package:miria/providers.dart';
import 'package:miria/router/app_router.dart';
Expand Down Expand Up @@ -105,15 +106,17 @@ class TabSettingsListItem extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final account = ref.watch(accountProvider(tabSetting.acct));
final account = tabSetting.acct.username.isEmpty
? Account.demoAccount(tabSetting.acct.host, null)
: ref.watch(accountProvider(tabSetting.acct));
return ListTile(
leading: AccountScope(
account: account,
child: TabIconView(icon: tabSetting.icon),
),
title: Text(tabSetting.name ?? tabSetting.tabType.displayName(context)),
subtitle: Text(
"${tabSetting.tabType.displayName(context)} / ${tabSetting.acct}",
"${tabSetting.tabType.displayName(context)} / ${tabSetting.acct.username.isEmpty ? tabSetting.acct.host : tabSetting.acct}",
),
trailing: const Icon(Icons.drag_handle),
onTap: () => context.pushRoute(TabSettingsRoute(tabIndex: index)),
Expand Down
77 changes: 65 additions & 12 deletions lib/view/settings_page/tab_settings_page/tab_settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:miria/providers.dart';
import 'package:miria/view/common/account_scope.dart';
import 'package:miria/view/common/tab_icon_view.dart';
import 'package:miria/view/dialogs/simple_message_dialog.dart';
import 'package:miria/view/login_page/misskey_server_list_dialog.dart';
import 'package:miria/view/settings_page/tab_settings_page/antenna_select_dialog.dart';
import 'package:miria/view/settings_page/tab_settings_page/channel_select_dialog.dart';
import 'package:miria/view/settings_page/tab_settings_page/icon_select_dialog.dart';
Expand All @@ -31,6 +32,7 @@ class TabSettingsPage extends ConsumerStatefulWidget {

class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
late Account? selectedAccount = ref.read(accountsProvider).first;
TextEditingController hostController = TextEditingController();
TabType? selectedTabType = TabType.localTimeline;
RolesListResponse? selectedRole;
CommunityChannel? selectedChannel;
Expand All @@ -55,7 +57,12 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
if (tab != null) {
final tabSetting =
ref.read(tabSettingsRepositoryProvider).tabSettings.toList()[tab];
selectedAccount = ref.read(accountProvider(tabSetting.acct));
if (tabSetting.acct.username.isEmpty) {
selectedAccount = null;
hostController.text = tabSetting.acct.host;
} else {
selectedAccount = ref.read(accountProvider(tabSetting.acct));
}
selectedTabType = tabSetting.tabType;
final roleId = tabSetting.roleId;
final channelId = tabSetting.channelId;
Expand Down Expand Up @@ -152,6 +159,7 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
Text(S.of(context).account),
DropdownButton<Account>(
items: [
const DropdownMenuItem(child: Text("なし")),
for (final account in accounts)
DropdownMenuItem(
value: account,
Expand All @@ -161,21 +169,51 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
onChanged: (value) {
setState(() {
selectedAccount = value;
selectedTabType = null;
selectedAntenna = null;
selectedUserList = null;
selectedChannel = null;
nameController.clear();
if (selectedIcon?.customEmojiName != null) {
selectedIcon = null;
}
});
},
value: selectedAccount,
),
if (selectedAccount == null) ...[
const Padding(padding: EdgeInsets.all(10)),
Text(S.of(context).server),
TextField(
controller: hostController,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.dns),
suffixIcon: IconButton(
onPressed: () async {
final url = await showDialog<String?>(
context: context,
builder: (context) => const MisskeyServerListDialog(),
);
if (url != null && url.isNotEmpty) {
hostController.text = url;
}
},
icon: const Icon(Icons.search),
),
),
),
],
const Padding(padding: EdgeInsets.all(10)),
Text(S.of(context).tabType),
DropdownButton<TabType>(
items: [
for (final tabType in TabType.values)
for (final tabType in TabType.values.where(
(tabType) =>
selectedAccount != null ||
tabType == TabType.localTimeline ||
tabType == TabType.globalTimeline ||
tabType == TabType.channel,
))
DropdownMenuItem(
value: tabType,
child: Text(tabType.displayName(context)),
Expand Down Expand Up @@ -221,13 +259,15 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
Expanded(child: Text(selectedChannel?.name ?? "")),
IconButton(
onPressed: () async {
final selected = selectedAccount;
if (selected == null) return;
final account = selectedAccount;
final host = hostController.text;
if (account == null && host.isEmpty) return;

selectedChannel = await showDialog<CommunityChannel>(
context: context,
builder: (context) =>
ChannelSelectDialog(account: selected),
builder: (context) => ChannelSelectDialog(
account: account ?? Account.demoAccount(host, null),
),
);
setState(() {
nameController.text =
Expand Down Expand Up @@ -300,10 +340,12 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
Row(
children: [
Expanded(
child: selectedAccount == null
child: selectedAccount == null &&
hostController.text.isEmpty
? Container()
: AccountScope(
account: selectedAccount!,
account: selectedAccount ??
Account.demoAccount(hostController.text, null),
child: SizedBox(
height: 32,
child: TabIconView(
Expand All @@ -315,11 +357,21 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
),
IconButton(
onPressed: () async {
if (selectedAccount == null) return;
final host = hostController.text;
final demoAccount = Account.demoAccount(host, null);
if (selectedAccount == null) {
if (host.isEmpty) {
return;
}
ref
.read(emojiRepositoryProvider(demoAccount))
.loadFromSourceIfNeed();
}
if (!mounted) return;
selectedIcon = await showDialog<TabIcon>(
context: context,
builder: (context) => IconSelectDialog(
account: selectedAccount!,
account: selectedAccount ?? demoAccount,
),
);
setState(() {});
Expand Down Expand Up @@ -369,7 +421,8 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
child: ElevatedButton(
onPressed: () async {
final account = selectedAccount;
if (account == null) {
final host = hostController.text;
if (account == null && host.isEmpty) {
SimpleMessageDialog.show(
context,
S.of(context).pleaseSelectAccount,
Expand Down Expand Up @@ -436,7 +489,7 @@ class TabSettingsAddDialogState extends ConsumerState<TabSettingsPage> {
icon: icon,
tabType: tabType,
name: nameController.text,
acct: account.acct,
acct: (account ?? Account.demoAccount(host, null)).acct,
roleId: selectedRole?.id,
channelId: selectedChannel?.id,
listId: selectedUserList?.id,
Expand Down
15 changes: 15 additions & 0 deletions lib/view/splash_page/splash_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:miria/licenses.dart';
import 'package:miria/model/account.dart';
import 'package:miria/providers.dart';
import 'package:miria/router/app_router.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
Expand Down Expand Up @@ -34,6 +35,20 @@ class SplashPageState extends ConsumerState<SplashPage> {
ref.read(mainStreamRepositoryProvider(account)).connect();
}

await Future.wait(
ref
.read(tabSettingsRepositoryProvider)
.tabSettings
.where((tabSetting) => tabSetting.acct.username.isEmpty)
.map((tabSetting) => tabSetting.acct.host)
.toSet()
.map(
(host) => ref
.read(emojiRepositoryProvider(Account.demoAccount(host, null)))
.loadFromLocalCache(),
),
);

if (_isFirst) {
if (Platform.isAndroid || Platform.isIOS) {
initialSharingMedias = (await ReceiveSharingIntent.getInitialMedia())
Expand Down
Loading

0 comments on commit 25eaaa3

Please sign in to comment.