Compare commits
6 Commits
1.2.1+35
...
db808650e3
| Author | SHA1 | Date | |
|---|---|---|---|
| db808650e3 | |||
| c1cbcbe734 | |||
| 2c4040096f | |||
| b449735bf5 | |||
| dd01f964d4 | |||
| 6daa04c208 |
@@ -76,8 +76,8 @@
|
|||||||
"firstName": "First Name",
|
"firstName": "First Name",
|
||||||
"lastName": "Last Name",
|
"lastName": "Last Name",
|
||||||
"account": "Account",
|
"account": "Account",
|
||||||
"accountPersonalize": "Personalize",
|
"accountProfile": "Your profile",
|
||||||
"accountPersonalizeApplied": "Account personalize settings has been saved.",
|
"accountProfileApplied": "Account profile has been saved.",
|
||||||
"accountStickers": "Stickers",
|
"accountStickers": "Stickers",
|
||||||
"accountFriend": "Friend",
|
"accountFriend": "Friend",
|
||||||
"accountFriendNew": "New friend",
|
"accountFriendNew": "New friend",
|
||||||
@@ -391,5 +391,6 @@
|
|||||||
"userLevel10": "Grandmaster",
|
"userLevel10": "Grandmaster",
|
||||||
"userLevel11": "Legend",
|
"userLevel11": "Legend",
|
||||||
"userLevel12": "Mythic",
|
"userLevel12": "Mythic",
|
||||||
"userLevel13": "Immortal"
|
"userLevel13": "Immortal",
|
||||||
|
"postBrowsingIn": "Browsing in @region"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@
|
|||||||
"firstName": "名称",
|
"firstName": "名称",
|
||||||
"lastName": "姓氏",
|
"lastName": "姓氏",
|
||||||
"account": "账号",
|
"account": "账号",
|
||||||
"accountPersonalize": "个性化",
|
"accountProfile": "个人资料",
|
||||||
"accountPersonalizeApplied": "账户的个性化设置已保存。",
|
"accountProfileApplied": "账户的资料已保存。",
|
||||||
"accountStickers": "贴图",
|
"accountStickers": "贴图",
|
||||||
"accountFriend": "好友",
|
"accountFriend": "好友",
|
||||||
"accountFriendNew": "添加好友",
|
"accountFriendNew": "添加好友",
|
||||||
@@ -392,5 +392,6 @@
|
|||||||
"userLevel10": "出神入化",
|
"userLevel10": "出神入化",
|
||||||
"userLevel11": "名垂千古",
|
"userLevel11": "名垂千古",
|
||||||
"userLevel12": "独占鳌头",
|
"userLevel12": "独占鳌头",
|
||||||
"userLevel13": "万古流芳"
|
"userLevel13": "万古流芳",
|
||||||
|
"postBrowsingIn": "浏览 @region 内的帖子中"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ PODS:
|
|||||||
- Firebase/Analytics (= 11.0.0)
|
- Firebase/Analytics (= 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_core (3.4.0):
|
- firebase_core (3.4.1):
|
||||||
- Firebase/CoreOnly (= 11.0.0)
|
- Firebase/CoreOnly (= 11.0.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_crashlytics (4.1.0):
|
- firebase_crashlytics (4.1.0):
|
||||||
@@ -221,7 +221,7 @@ PODS:
|
|||||||
- TOCropViewController (~> 2.7.4)
|
- TOCropViewController (~> 2.7.4)
|
||||||
- image_picker_ios (0.0.1):
|
- image_picker_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- livekit_client (2.2.4):
|
- livekit_client (2.2.5):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (= 125.6422.04)
|
- WebRTC-SDK (= 125.6422.04)
|
||||||
- media_kit_libs_ios_video (1.0.4):
|
- media_kit_libs_ios_video (1.0.4):
|
||||||
@@ -414,7 +414,7 @@ SPEC CHECKSUMS:
|
|||||||
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
|
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
|
||||||
Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9
|
Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9
|
||||||
firebase_analytics: 1a66fe8d4375eccff44671ea37897683a78b2675
|
firebase_analytics: 1a66fe8d4375eccff44671ea37897683a78b2675
|
||||||
firebase_core: ceec591a66629daaee82d3321551692c4a871493
|
firebase_core: ba84e940cf5cbbc601095f86556560937419195c
|
||||||
firebase_crashlytics: e4f04180f443d5a8b56fbc0685bdbd7d90dd26f0
|
firebase_crashlytics: e4f04180f443d5a8b56fbc0685bdbd7d90dd26f0
|
||||||
firebase_messaging: 15d8b557010f3bb7b98d0302e1c7c8fbcd244425
|
firebase_messaging: 15d8b557010f3bb7b98d0302e1c7c8fbcd244425
|
||||||
firebase_performance: d373c742649e2d85d92cc223b4511c3d132887ef
|
firebase_performance: d373c742649e2d85d92cc223b4511c3d132887ef
|
||||||
@@ -442,7 +442,7 @@ SPEC CHECKSUMS:
|
|||||||
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
||||||
image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf
|
image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf
|
||||||
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
|
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
|
||||||
livekit_client: d079c5f040d4bf2b80440ff0ae997725a183e4bc
|
livekit_client: 9c8080879256a0fb16da13c9be4845248209d896
|
||||||
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
||||||
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
||||||
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
||||||
|
|||||||
@@ -155,13 +155,14 @@ class PostEditorController extends GetxController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void localRead() {
|
Future<bool> localRead() async {
|
||||||
SharedPreferences.getInstance().then((inst) {
|
final inst = await SharedPreferences.getInstance();
|
||||||
if (inst.containsKey('post_editor_local_save')) {
|
if (inst.containsKey('post_editor_local_save')) {
|
||||||
isRestoreFromLocal.value = true;
|
isRestoreFromLocal.value = true;
|
||||||
payload = jsonDecode(inst.getString('post_editor_local_save')!);
|
payload = jsonDecode(inst.getString('post_editor_local_save')!);
|
||||||
}
|
return true;
|
||||||
});
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void localClear() {
|
void localClear() {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import 'package:solian/providers/last_read.dart';
|
|||||||
|
|
||||||
class PostListController extends GetxController {
|
class PostListController extends GetxController {
|
||||||
String? author;
|
String? author;
|
||||||
|
String? realm;
|
||||||
|
|
||||||
/// The polling source modifier.
|
/// The polling source modifier.
|
||||||
/// - `0`: default recommendations
|
/// - `0`: default recommendations
|
||||||
@@ -99,8 +100,10 @@ class PostListController extends GetxController {
|
|||||||
final idx = <dynamic>{};
|
final idx = <dynamic>{};
|
||||||
postList.retainWhere((x) => idx.add(x.id));
|
postList.retainWhere((x) => idx.add(x.id));
|
||||||
|
|
||||||
var lastId = postList.map((x) => x.id).reduce(max);
|
if (postList.isNotEmpty) {
|
||||||
Get.find<LastReadProvider>().feedLastReadAt = lastId;
|
var lastId = postList.map((x) => x.id).reduce(max);
|
||||||
|
Get.find<LastReadProvider>().feedLastReadAt = lastId;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -123,16 +126,21 @@ class PostListController extends GetxController {
|
|||||||
resp = await provider.listRecommendations(
|
resp = await provider.listRecommendations(
|
||||||
pageKey,
|
pageKey,
|
||||||
channel: 'shuffle',
|
channel: 'shuffle',
|
||||||
|
realm: realm,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
resp = await provider.listRecommendations(
|
resp = await provider.listRecommendations(
|
||||||
pageKey,
|
pageKey,
|
||||||
channel: 'friends',
|
channel: 'friends',
|
||||||
|
realm: realm,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
resp = await provider.listRecommendations(pageKey);
|
resp = await provider.listRecommendations(
|
||||||
|
pageKey,
|
||||||
|
realm: realm,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import 'package:solian/providers/attachment_uploader.dart';
|
|||||||
import 'package:solian/providers/daily_sign.dart';
|
import 'package:solian/providers/daily_sign.dart';
|
||||||
import 'package:solian/providers/last_read.dart';
|
import 'package:solian/providers/last_read.dart';
|
||||||
import 'package:solian/providers/link_expander.dart';
|
import 'package:solian/providers/link_expander.dart';
|
||||||
|
import 'package:solian/providers/navigation.dart';
|
||||||
import 'package:solian/providers/stickers.dart';
|
import 'package:solian/providers/stickers.dart';
|
||||||
import 'package:solian/providers/theme_switcher.dart';
|
import 'package:solian/providers/theme_switcher.dart';
|
||||||
import 'package:solian/providers/websocket.dart';
|
import 'package:solian/providers/websocket.dart';
|
||||||
@@ -79,8 +80,8 @@ Future<void> _initializePlatformComponents() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final themeSwitcher = ThemeSwitcher(
|
final themeSwitcher = ThemeSwitcher(
|
||||||
lightThemeData: SolianTheme.build(Brightness.light),
|
lightThemeData: AppTheme.build(Brightness.light),
|
||||||
darkThemeData: SolianTheme.build(Brightness.dark),
|
darkThemeData: AppTheme.build(Brightness.dark),
|
||||||
);
|
);
|
||||||
|
|
||||||
class SolianApp extends StatelessWidget {
|
class SolianApp extends StatelessWidget {
|
||||||
@@ -123,6 +124,8 @@ class SolianApp extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _initializeProviders(BuildContext context) async {
|
void _initializeProviders(BuildContext context) async {
|
||||||
|
Get.put(NavigationStateProvider());
|
||||||
|
|
||||||
Get.lazyPut(() => AuthProvider());
|
Get.lazyPut(() => AuthProvider());
|
||||||
Get.lazyPut(() => RelationshipProvider());
|
Get.lazyPut(() => RelationshipProvider());
|
||||||
Get.lazyPut(() => PostProvider());
|
Get.lazyPut(() => PostProvider());
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ class Realm {
|
|||||||
String alias;
|
String alias;
|
||||||
String name;
|
String name;
|
||||||
String description;
|
String description;
|
||||||
|
String? avatar;
|
||||||
|
String? banner;
|
||||||
bool isPublic;
|
bool isPublic;
|
||||||
bool isCommunity;
|
bool isCommunity;
|
||||||
int? accountId;
|
int? accountId;
|
||||||
|
int? externalId;
|
||||||
|
|
||||||
Realm({
|
Realm({
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -24,9 +27,12 @@ class Realm {
|
|||||||
required this.alias,
|
required this.alias,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.description,
|
required this.description,
|
||||||
|
required this.avatar,
|
||||||
|
required this.banner,
|
||||||
required this.isPublic,
|
required this.isPublic,
|
||||||
required this.isCommunity,
|
required this.isCommunity,
|
||||||
this.accountId,
|
this.accountId,
|
||||||
|
this.externalId,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Realm.fromJson(Map<String, dynamic> json) => _$RealmFromJson(json);
|
factory Realm.fromJson(Map<String, dynamic> json) => _$RealmFromJson(json);
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ Realm _$RealmFromJson(Map<String, dynamic> json) => Realm(
|
|||||||
alias: json['alias'] as String,
|
alias: json['alias'] as String,
|
||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
description: json['description'] as String,
|
description: json['description'] as String,
|
||||||
|
avatar: json['avatar'] as String?,
|
||||||
|
banner: json['banner'] as String?,
|
||||||
isPublic: json['is_public'] as bool,
|
isPublic: json['is_public'] as bool,
|
||||||
isCommunity: json['is_community'] as bool,
|
isCommunity: json['is_community'] as bool,
|
||||||
accountId: (json['account_id'] as num?)?.toInt(),
|
accountId: (json['account_id'] as num?)?.toInt(),
|
||||||
|
externalId: (json['external_id'] as num?)?.toInt(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$RealmToJson(Realm instance) => <String, dynamic>{
|
Map<String, dynamic> _$RealmToJson(Realm instance) => <String, dynamic>{
|
||||||
@@ -29,9 +32,12 @@ Map<String, dynamic> _$RealmToJson(Realm instance) => <String, dynamic>{
|
|||||||
'alias': instance.alias,
|
'alias': instance.alias,
|
||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'description': instance.description,
|
'description': instance.description,
|
||||||
|
'avatar': instance.avatar,
|
||||||
|
'banner': instance.banner,
|
||||||
'is_public': instance.isPublic,
|
'is_public': instance.isPublic,
|
||||||
'is_community': instance.isCommunity,
|
'is_community': instance.isCommunity,
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
|
'external_id': instance.externalId,
|
||||||
};
|
};
|
||||||
|
|
||||||
RealmMember _$RealmMemberFromJson(Map<String, dynamic> json) => RealmMember(
|
RealmMember _$RealmMemberFromJson(Map<String, dynamic> json) => RealmMember(
|
||||||
|
|||||||
6
lib/providers/navigation.dart
Normal file
6
lib/providers/navigation.dart
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:solian/models/realm.dart';
|
||||||
|
|
||||||
|
class NavigationStateProvider extends GetxController {
|
||||||
|
final Rx<Realm?> focusedRealm = Rx(null);
|
||||||
|
}
|
||||||
@@ -16,8 +16,8 @@ class ThemeSwitcher extends ChangeNotifier {
|
|||||||
if (prefs.containsKey('global_theme_color')) {
|
if (prefs.containsKey('global_theme_color')) {
|
||||||
final value = prefs.getInt('global_theme_color')!;
|
final value = prefs.getInt('global_theme_color')!;
|
||||||
final color = Color(value);
|
final color = Color(value);
|
||||||
lightThemeData = SolianTheme.build(Brightness.light, seedColor: color);
|
lightThemeData = AppTheme.build(Brightness.light, seedColor: color);
|
||||||
darkThemeData = SolianTheme.build(Brightness.dark, seedColor: color);
|
darkThemeData = AppTheme.build(Brightness.dark, seedColor: color);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ abstract class AppRouter {
|
|||||||
name: 'channelChat',
|
name: 'channelChat',
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return ChannelChatScreen(
|
return ChannelChatScreen(
|
||||||
|
key: UniqueKey(),
|
||||||
alias: state.pathParameters['alias']!,
|
alias: state.pathParameters['alias']!,
|
||||||
realm: state.uri.queryParameters['realm'] ?? 'global',
|
realm: state.uri.queryParameters['realm'] ?? 'global',
|
||||||
);
|
);
|
||||||
@@ -245,7 +246,7 @@ abstract class AppRouter {
|
|||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/account/personalize',
|
path: '/account/personalize',
|
||||||
name: 'accountPersonalize',
|
name: 'accountProfile',
|
||||||
builder: (context, state) => TitleShell(
|
builder: (context, state) => TitleShell(
|
||||||
state: state,
|
state: state,
|
||||||
child: const PersonalizeScreen(),
|
child: const PersonalizeScreen(),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:solian/models/account.dart';
|
import 'package:solian/models/account.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
@@ -23,9 +24,9 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final actionItems = [
|
final actionItems = [
|
||||||
(
|
(
|
||||||
const Icon(Icons.color_lens),
|
const Icon(Icons.face),
|
||||||
'accountPersonalize'.tr,
|
'accountProfile'.tr,
|
||||||
'accountPersonalize',
|
'accountProfile',
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Obx(() {
|
Obx(() {
|
||||||
@@ -47,9 +48,9 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
'accountFriend',
|
'accountFriend',
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
const Icon(Icons.emoji_symbols),
|
const Icon(Icons.emoji_symbols),
|
||||||
'accountStickers'.tr,
|
'accountStickers'.tr,
|
||||||
'accountStickers',
|
'accountStickers',
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ActionCard(
|
_ActionCard(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.login,
|
Icons.login,
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
@@ -85,7 +86,7 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ActionCard(
|
_ActionCard(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.add,
|
Icons.add,
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
@@ -104,6 +105,19 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
const Gap(4),
|
||||||
|
TextButton(
|
||||||
|
style: const ButtonStyle(
|
||||||
|
visualDensity: VisualDensity(
|
||||||
|
horizontal: -4,
|
||||||
|
vertical: -2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
AppRouter.instance.pushNamed('settings');
|
||||||
|
},
|
||||||
|
child: Text('settings'.tr),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -126,6 +140,18 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
const Divider(thickness: 0.3, height: 1)
|
||||||
|
.paddingSymmetric(vertical: 4),
|
||||||
|
ListTile(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 34),
|
||||||
|
leading: const Icon(Icons.settings),
|
||||||
|
title: Text('settings'.tr),
|
||||||
|
onTap: () {
|
||||||
|
AppRouter.instance.pushNamed('settings');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Divider(thickness: 0.3, height: 1)
|
||||||
|
.paddingSymmetric(vertical: 4),
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 34),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 34),
|
||||||
leading: const Icon(Icons.logout),
|
leading: const Icon(Icons.logout),
|
||||||
@@ -186,13 +212,13 @@ class _AccountHeadingState extends State<AccountHeading> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActionCard extends StatelessWidget {
|
class _ActionCard extends StatelessWidget {
|
||||||
final Widget icon;
|
final Widget icon;
|
||||||
final String title;
|
final String title;
|
||||||
final String caption;
|
final String caption;
|
||||||
final Function onTap;
|
final Function onTap;
|
||||||
|
|
||||||
const ActionCard({
|
const _ActionCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
required this.title,
|
required this.title,
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class _FriendScreenState extends State<FriendScreen>
|
|||||||
).paddingAll(14),
|
).paddingAll(14),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
);
|
);
|
||||||
if (resp.statusCode == 200) {
|
if (resp.statusCode == 200) {
|
||||||
_syncWidget();
|
_syncWidget();
|
||||||
context.showSnackbar('accountPersonalizeApplied'.tr);
|
context.showSnackbar('accountProfileApplied'.tr);
|
||||||
} else {
|
} else {
|
||||||
context.showErrorDialog(resp.bodyString);
|
context.showErrorDialog(resp.bodyString);
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
);
|
);
|
||||||
if (resp.statusCode == 200) {
|
if (resp.statusCode == 200) {
|
||||||
_syncWidget();
|
_syncWidget();
|
||||||
context.showSnackbar('accountPersonalizeApplied'.tr);
|
context.showSnackbar('accountProfileApplied'.tr);
|
||||||
} else {
|
} else {
|
||||||
context.showErrorDialog(resp.bodyString);
|
context.showErrorDialog(resp.bodyString);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
|||||||
SliverAppBar(
|
SliverAppBar(
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
floating: true,
|
floating: true,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
leadingWidth: 24,
|
leadingWidth: 24,
|
||||||
automaticallyImplyLeading: false,
|
automaticallyImplyLeading: false,
|
||||||
flexibleSpace: Row(
|
flexibleSpace: Row(
|
||||||
@@ -207,7 +207,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
|||||||
onPressed: null,
|
onPressed: null,
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
|
|||||||
: AppBar(
|
: AppBar(
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
title: Obx(
|
title: Obx(
|
||||||
() => RichText(
|
() => RichText(
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
|||||||
@@ -217,8 +217,8 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle(title),
|
title: AppBarTitle(title),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
titleSpacing: SolianTheme.titleSpacing(context),
|
titleSpacing: AppTheme.titleSpacing(context),
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
const BackgroundStateWidget(),
|
const BackgroundStateWidget(),
|
||||||
Builder(builder: (context) {
|
Builder(builder: (context) {
|
||||||
@@ -255,7 +255,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -276,7 +276,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
channel: _channel!,
|
channel: _channel!,
|
||||||
ongoingCall: _ongoingCall!,
|
ongoingCall: _ongoingCall!,
|
||||||
onJoin: () {
|
onJoin: () {
|
||||||
if (!SolianTheme.isLargeScreen(context)) {
|
if (!AppTheme.isLargeScreen(context)) {
|
||||||
final ChatCallProvider call = Get.find();
|
final ChatCallProvider call = Get.find();
|
||||||
call.gotoScreen(context);
|
call.gotoScreen(context);
|
||||||
}
|
}
|
||||||
@@ -337,7 +337,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
),
|
),
|
||||||
Obx(() {
|
Obx(() {
|
||||||
final ChatCallProvider call = Get.find();
|
final ChatCallProvider call = Get.find();
|
||||||
if (call.isMounted.value && SolianTheme.isLargeScreen(context)) {
|
if (call.isMounted.value && AppTheme.isLargeScreen(context)) {
|
||||||
return const Expanded(
|
return const Expanded(
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
VerticalDivider(width: 0.3, thickness: 0.3),
|
VerticalDivider(width: 0.3, thickness: 0.3),
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: AppBarTitle('channelOrganizing'.tr),
|
title: AppBarTitle('channelOrganizing'.tr),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _isBusy ? null : () => applyChannel(),
|
onPressed: _isBusy ? null : () => applyChannel(),
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle('chat'.tr),
|
title: AppBarTitle('chat'.tr),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
const BackgroundStateWidget(),
|
const BackgroundStateWidget(),
|
||||||
const NotificationButton(),
|
const NotificationButton(),
|
||||||
@@ -95,7 +95,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
|||||||
Card(
|
Card(
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(horizontal: 24),
|
const EdgeInsets.only(left: 24, right: 32),
|
||||||
trailing: const Icon(Icons.inbox_outlined),
|
trailing: const Icon(Icons.inbox_outlined),
|
||||||
title: Text('notifyEmpty'.tr),
|
title: Text('notifyEmpty'.tr),
|
||||||
subtitle: Text('notifyEmptyCaption'.tr),
|
subtitle: Text('notifyEmptyCaption'.tr),
|
||||||
@@ -368,18 +368,23 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
|||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: min(480, width),
|
width: min(480, width),
|
||||||
child: Card(
|
child: Card(
|
||||||
child: SingleChildScrollView(
|
child: ClipRRect(
|
||||||
child: PostListEntryWidget(
|
borderRadius: const BorderRadius.all(
|
||||||
item: item,
|
Radius.circular(8),
|
||||||
isClickable: true,
|
),
|
||||||
isShowEmbed: true,
|
child: SingleChildScrollView(
|
||||||
isNestedClickable: true,
|
child: PostListEntryWidget(
|
||||||
onUpdate: (_) {
|
item: item,
|
||||||
_pullPosts();
|
isClickable: true,
|
||||||
},
|
isShowEmbed: true,
|
||||||
backgroundColor: Theme.of(context)
|
isNestedClickable: true,
|
||||||
.colorScheme
|
onUpdate: (_) {
|
||||||
.surfaceContainerLow,
|
_pullPosts();
|
||||||
|
},
|
||||||
|
backgroundColor: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.surfaceContainerLow,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
).paddingSymmetric(horizontal: 8),
|
).paddingSymmetric(horizontal: 8),
|
||||||
@@ -499,7 +504,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
|||||||
|
|
||||||
/// Footer
|
/// Footer
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: SolianTheme.isLargeScreen(context)
|
mainAxisAlignment: AppTheme.isLargeScreen(context)
|
||||||
? MainAxisAlignment.start
|
? MainAxisAlignment.start
|
||||||
: MainAxisAlignment.center,
|
: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:solian/controllers/post_list_controller.dart';
|
import 'package:solian/controllers/post_list_controller.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
|
import 'package:solian/providers/navigation.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/screens/account/notification.dart';
|
import 'package:solian/screens/account/notification.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
@@ -25,21 +28,34 @@ class _FeedScreenState extends State<FeedScreen>
|
|||||||
late final PostListController _postController;
|
late final PostListController _postController;
|
||||||
late final TabController _tabController;
|
late final TabController _tabController;
|
||||||
|
|
||||||
|
List<StreamSubscription>? _subscriptions;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
final navState = Get.find<NavigationStateProvider>();
|
||||||
_postController = PostListController();
|
_postController = PostListController();
|
||||||
|
_postController.realm = navState.focusedRealm.value?.alias;
|
||||||
_tabController = TabController(length: 3, vsync: this);
|
_tabController = TabController(length: 3, vsync: this);
|
||||||
_tabController.addListener(() {
|
_tabController.addListener(() {
|
||||||
if (_postController.mode.value == _tabController.index) return;
|
if (_postController.mode.value == _tabController.index) return;
|
||||||
_postController.mode.value = _tabController.index;
|
_postController.mode.value = _tabController.index;
|
||||||
_postController.reloadAllOver();
|
_postController.reloadAllOver();
|
||||||
});
|
});
|
||||||
|
_subscriptions = [
|
||||||
|
Get.find<NavigationStateProvider>().focusedRealm.listen((value) {
|
||||||
|
if (value?.alias != _postController.realm) {
|
||||||
|
_postController.realm = value?.alias;
|
||||||
|
_postController.reloadAllOver();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
|
final NavigationStateProvider navState = Get.find();
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
@@ -69,13 +85,13 @@ class _FeedScreenState extends State<FeedScreen>
|
|||||||
title: AppBarTitle('feed'.tr),
|
title: AppBarTitle('feed'.tr),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
floating: true,
|
floating: true,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
actions: [
|
actions: [
|
||||||
const BackgroundStateWidget(),
|
const BackgroundStateWidget(),
|
||||||
const NotificationButton(),
|
const NotificationButton(),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
@@ -96,37 +112,53 @@ class _FeedScreenState extends State<FeedScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TabBarView(
|
return Column(
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
controller: _tabController,
|
|
||||||
children: [
|
children: [
|
||||||
RefreshIndicator(
|
if (navState.focusedRealm.value != null)
|
||||||
onRefresh: () => _postController.reloadAllOver(),
|
MaterialBanner(
|
||||||
child: CustomScrollView(slivers: [
|
leading: const Icon(Icons.layers),
|
||||||
PostWarpedListWidget(
|
content: Text(
|
||||||
controller: _postController.pagingController,
|
'postBrowsingIn'.trParams({
|
||||||
onUpdate: () => _postController.reloadAllOver(),
|
'region': '#${navState.focusedRealm.value!.alias}',
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
]),
|
actions: const [SizedBox.shrink()],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
controller: _tabController,
|
||||||
|
children: [
|
||||||
|
RefreshIndicator(
|
||||||
|
onRefresh: () => _postController.reloadAllOver(),
|
||||||
|
child: CustomScrollView(slivers: [
|
||||||
|
PostWarpedListWidget(
|
||||||
|
controller: _postController.pagingController,
|
||||||
|
onUpdate: () => _postController.reloadAllOver(),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
Obx(() {
|
||||||
|
if (auth.isAuthorized.value) {
|
||||||
|
return RefreshIndicator(
|
||||||
|
onRefresh: () => _postController.reloadAllOver(),
|
||||||
|
child: CustomScrollView(slivers: [
|
||||||
|
PostWarpedListWidget(
|
||||||
|
controller: _postController.pagingController,
|
||||||
|
onUpdate: () => _postController.reloadAllOver(),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return SigninRequiredOverlay(
|
||||||
|
onSignedIn: () => _postController.reloadAllOver(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
PostShuffleSwiper(controller: _postController),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Obx(() {
|
|
||||||
if (auth.isAuthorized.value) {
|
|
||||||
return RefreshIndicator(
|
|
||||||
onRefresh: () => _postController.reloadAllOver(),
|
|
||||||
child: CustomScrollView(slivers: [
|
|
||||||
PostWarpedListWidget(
|
|
||||||
controller: _postController.pagingController,
|
|
||||||
onUpdate: () => _postController.reloadAllOver(),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return SigninRequiredOverlay(
|
|
||||||
onSignedIn: () => _postController.reloadAllOver(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
PostShuffleSwiper(controller: _postController),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
@@ -138,6 +170,11 @@ class _FeedScreenState extends State<FeedScreen>
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_postController.dispose();
|
_postController.dispose();
|
||||||
|
if (_subscriptions != null) {
|
||||||
|
for (final subscription in _subscriptions!) {
|
||||||
|
subscription.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,10 +61,10 @@ class _DraftBoxScreenState extends State<DraftBoxScreen> {
|
|||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle('draftBox'.tr),
|
title: AppBarTitle('draftBox'.tr),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:solian/models/post.dart';
|
|||||||
import 'package:solian/models/realm.dart';
|
import 'package:solian/models/realm.dart';
|
||||||
import 'package:solian/providers/attachment_uploader.dart';
|
import 'package:solian/providers/attachment_uploader.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
|
import 'package:solian/providers/navigation.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
import 'package:solian/widgets/app_bar_leading.dart';
|
import 'package:solian/widgets/app_bar_leading.dart';
|
||||||
@@ -124,7 +125,12 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (widget.edit == null && widget.reply == null && widget.repost == null) {
|
if (widget.edit == null && widget.reply == null && widget.repost == null) {
|
||||||
_editorController.localRead();
|
_editorController.localRead().then((res) {
|
||||||
|
if (!res) {
|
||||||
|
final navState = Get.find<NavigationStateProvider>();
|
||||||
|
_editorController.realmZone.value = navState.focusedRealm.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (widget.reply != null) {
|
if (widget.reply != null) {
|
||||||
_editorController.replyTo.value = widget.reply;
|
_editorController.replyTo.value = widget.reply;
|
||||||
@@ -158,7 +164,7 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _isBusy ? null : () => _applyPost(),
|
onPressed: _isBusy ? null : () => _applyPost(),
|
||||||
@@ -177,23 +183,19 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
tileColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
tileColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
title: SingleChildScrollView(
|
title: Row(
|
||||||
scrollDirection: Axis.horizontal,
|
children: [
|
||||||
child: Row(
|
Text(
|
||||||
children: [
|
_editorController.title ?? 'title'.tr,
|
||||||
Text(
|
maxLines: 1,
|
||||||
_editorController.title ?? 'title'.tr,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
const Gap(6),
|
||||||
|
if (_editorController.aliasController.text.isNotEmpty)
|
||||||
|
Badge(
|
||||||
|
label: Text('#${_editorController.aliasController.text}'),
|
||||||
),
|
),
|
||||||
const Gap(6),
|
],
|
||||||
if (_editorController.aliasController.text.isNotEmpty)
|
|
||||||
Badge(
|
|
||||||
label:
|
|
||||||
Text('#${_editorController.aliasController.text}'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
_editorController.description ?? 'description'.tr,
|
_editorController.description ?? 'description'.tr,
|
||||||
@@ -365,12 +367,12 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (SolianTheme.isLargeScreen(context))
|
if (AppTheme.isLargeScreen(context))
|
||||||
const VerticalDivider(width: 0.3, thickness: 0.3)
|
const VerticalDivider(width: 0.3, thickness: 0.3)
|
||||||
.paddingSymmetric(
|
.paddingSymmetric(
|
||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
),
|
),
|
||||||
if (SolianTheme.isLargeScreen(context))
|
if (AppTheme.isLargeScreen(context))
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: MarkdownTextContent(
|
child: MarkdownTextContent(
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class _RealmListScreenState extends State<RealmListScreen> {
|
|||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle('realm'.tr),
|
title: AppBarTitle('realm'.tr),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
const BackgroundStateWidget(),
|
const BackgroundStateWidget(),
|
||||||
const NotificationButton(),
|
const NotificationButton(),
|
||||||
@@ -77,7 +77,7 @@ class _RealmListScreenState extends State<RealmListScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class _RealmOrganizeScreenState extends State<RealmOrganizeScreen> {
|
|||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle('realmOrganizing'.tr),
|
title: AppBarTitle('realmOrganizing'.tr),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _isBusy ? null : () => applyRealm(),
|
onPressed: _isBusy ? null : () => applyRealm(),
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class _RealmViewScreenState extends State<RealmViewScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
bottom: const TabBar(
|
bottom: const TabBar(
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ class _SettingScreenState extends State<SettingScreen> {
|
|||||||
tooltip: label,
|
tooltip: label,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.read<ThemeSwitcher>().setTheme(
|
context.read<ThemeSwitcher>().setTheme(
|
||||||
SolianTheme.build(
|
AppTheme.build(
|
||||||
Brightness.light,
|
Brightness.light,
|
||||||
seedColor: color,
|
seedColor: color,
|
||||||
),
|
),
|
||||||
SolianTheme.build(
|
AppTheme.build(
|
||||||
Brightness.dark,
|
Brightness.dark,
|
||||||
seedColor: color,
|
seedColor: color,
|
||||||
),
|
),
|
||||||
@@ -82,32 +82,27 @@ class _SettingScreenState extends State<SettingScreen> {
|
|||||||
).paddingSymmetric(horizontal: 12, vertical: 8),
|
).paddingSymmetric(horizontal: 12, vertical: 8),
|
||||||
),
|
),
|
||||||
_buildCaptionHeader('more'.tr),
|
_buildCaptionHeader('more'.tr),
|
||||||
Row(
|
ListTile(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
leading: const Icon(Icons.info_outline),
|
||||||
children: [
|
trailing: const Icon(Icons.chevron_right),
|
||||||
TextButton(
|
contentPadding: const EdgeInsets.symmetric(horizontal: 22),
|
||||||
style: const ButtonStyle(
|
title: Text('about'.tr),
|
||||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
onTap: () {
|
||||||
),
|
AppRouter.instance.pushNamed('about');
|
||||||
child: Text('about'.tr),
|
},
|
||||||
onPressed: () {
|
),
|
||||||
AppRouter.instance.pushNamed('about');
|
ListTile(
|
||||||
},
|
leading: const Icon(Icons.delete_sweep),
|
||||||
),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
TextButton(
|
contentPadding: const EdgeInsets.symmetric(horizontal: 22),
|
||||||
style: const ButtonStyle(
|
title: Text('messageHistoryWipe'.tr),
|
||||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
onTap: () {
|
||||||
),
|
final chatHistory = ChatEventController();
|
||||||
child: Text('messageHistoryWipe'.tr),
|
chatHistory.initialize().then((_) async {
|
||||||
onPressed: () {
|
await chatHistory.database.localEvents.wipeLocalEvents();
|
||||||
final chatHistory = ChatEventController();
|
});
|
||||||
chatHistory.initialize().then((_) async {
|
},
|
||||||
await chatHistory.database.localEvents.wipeLocalEvents();
|
),
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).paddingSymmetric(horizontal: 12, vertical: 8),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class CenteredShell extends StatelessWidget {
|
|||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr),
|
title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
body: Center(
|
body: Center(
|
||||||
|
|||||||
@@ -41,10 +41,10 @@ class RootShell extends StatelessWidget {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: rootScaffoldKey,
|
key: rootScaffoldKey,
|
||||||
drawer: SolianTheme.isLargeScreen(context)
|
drawer: AppTheme.isLargeScreen(context)
|
||||||
? null
|
? null
|
||||||
: AppNavigationDrawer(routeName: routeName),
|
: AppNavigationDrawer(routeName: routeName),
|
||||||
body: SolianTheme.isLargeScreen(context)
|
body: AppTheme.isLargeScreen(context)
|
||||||
? Row(
|
? Row(
|
||||||
children: [
|
children: [
|
||||||
if (showNavigation) AppNavigationDrawer(routeName: routeName),
|
if (showNavigation) AppNavigationDrawer(routeName: routeName),
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ class SidebarShell extends StatelessWidget {
|
|||||||
flex: 2,
|
flex: 2,
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
if (SolianTheme.isExtraLargeScreen(context))
|
if (AppTheme.isExtraLargeScreen(context))
|
||||||
const VerticalDivider(thickness: 0.3, width: 1),
|
const VerticalDivider(thickness: 0.3, width: 1),
|
||||||
if (SolianTheme.isExtraLargeScreen(context))
|
if (AppTheme.isExtraLargeScreen(context))
|
||||||
Flexible(
|
Flexible(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: sidebar ?? const SidebarPlaceholder(),
|
child: sidebar ?? const SidebarPlaceholder(),
|
||||||
@@ -47,10 +47,10 @@ class SidebarShell extends StatelessWidget {
|
|||||||
leading: AppBarLeadingButton.adaptive(context),
|
leading: AppBarLeadingButton.adaptive(context),
|
||||||
title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr),
|
title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
body: SolianTheme.isLargeScreen(context)
|
body: AppTheme.isLargeScreen(context)
|
||||||
? Row(
|
? Row(
|
||||||
children: sidebarFirst
|
children: sidebarFirst
|
||||||
? buildContent(context).reversed.toList()
|
? buildContent(context).reversed.toList()
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ class TitleShell extends StatelessWidget {
|
|||||||
title ?? (state!.topRoute?.name?.tr ?? 'page'.tr),
|
title ?? (state!.topRoute?.name?.tr ?? 'page'.tr),
|
||||||
),
|
),
|
||||||
centerTitle: isCenteredTitle,
|
centerTitle: isCenteredTitle,
|
||||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
||||||
actions: [
|
actions: [
|
||||||
const BackgroundStateWidget(),
|
const BackgroundStateWidget(),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:solian/platform.dart';
|
import 'package:solian/platform.dart';
|
||||||
|
|
||||||
abstract class SolianTheme {
|
abstract class AppTheme {
|
||||||
static bool isLargeScreen(BuildContext context) =>
|
static bool isLargeScreen(BuildContext context) =>
|
||||||
MediaQuery.of(context).size.width > 640;
|
MediaQuery.of(context).size.width > 640;
|
||||||
|
|
||||||
@@ -9,13 +9,13 @@ abstract class SolianTheme {
|
|||||||
MediaQuery.of(context).size.width > 720;
|
MediaQuery.of(context).size.width > 720;
|
||||||
|
|
||||||
static bool isSpecializedMacOS(BuildContext context) =>
|
static bool isSpecializedMacOS(BuildContext context) =>
|
||||||
PlatformInfo.isMacOS && !SolianTheme.isLargeScreen(context);
|
PlatformInfo.isMacOS && !AppTheme.isLargeScreen(context);
|
||||||
|
|
||||||
static double? titleSpacing(BuildContext context) {
|
static double? titleSpacing(BuildContext context) {
|
||||||
if (SolianTheme.isSpecializedMacOS(context)) {
|
if (AppTheme.isSpecializedMacOS(context)) {
|
||||||
return 24;
|
return 24;
|
||||||
} else {
|
} else {
|
||||||
return SolianTheme.isLargeScreen(context) ? null : 24;
|
return AppTheme.isLargeScreen(context) ? null : 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class AppBarTitle extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (SolianTheme.isSpecializedMacOS(context)) {
|
if (AppTheme.isSpecializedMacOS(context)) {
|
||||||
return Text(title);
|
return Text(title);
|
||||||
} else {
|
} else {
|
||||||
return Text(title);
|
return Text(title);
|
||||||
|
|||||||
@@ -98,12 +98,12 @@ class ChannelCallIndicator extends StatelessWidget {
|
|||||||
child: Text('callJoin'.tr),
|
child: Text('callJoin'.tr),
|
||||||
);
|
);
|
||||||
} else if (call.channel.value?.id == channel.id &&
|
} else if (call.channel.value?.id == channel.id &&
|
||||||
!SolianTheme.isLargeScreen(context)) {
|
!AppTheme.isLargeScreen(context)) {
|
||||||
return TextButton(
|
return TextButton(
|
||||||
onPressed: () => onJoin(),
|
onPressed: () => onJoin(),
|
||||||
child: Text('callResume'.tr),
|
child: Text('callResume'.tr),
|
||||||
);
|
);
|
||||||
} else if (!SolianTheme.isLargeScreen(context)) {
|
} else if (!AppTheme.isLargeScreen(context)) {
|
||||||
return TextButton(
|
return TextButton(
|
||||||
onPressed: null,
|
onPressed: null,
|
||||||
child: Text('callJoin'.tr),
|
child: Text('callJoin'.tr),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class ChannelListWidget extends StatefulWidget {
|
|||||||
final List<Channel> channels;
|
final List<Channel> channels;
|
||||||
final int selfId;
|
final int selfId;
|
||||||
final bool isDense;
|
final bool isDense;
|
||||||
|
final bool isCollapsed;
|
||||||
final bool noCategory;
|
final bool noCategory;
|
||||||
final bool useReplace;
|
final bool useReplace;
|
||||||
final Function(Channel)? onSelected;
|
final Function(Channel)? onSelected;
|
||||||
@@ -20,6 +21,7 @@ class ChannelListWidget extends StatefulWidget {
|
|||||||
required this.channels,
|
required this.channels,
|
||||||
required this.selfId,
|
required this.selfId,
|
||||||
this.isDense = false,
|
this.isDense = false,
|
||||||
|
this.isCollapsed = false,
|
||||||
this.noCategory = false,
|
this.noCategory = false,
|
||||||
this.useReplace = false,
|
this.useReplace = false,
|
||||||
this.onSelected,
|
this.onSelected,
|
||||||
@@ -130,13 +132,25 @@ class _ChannelListWidgetState extends State<ChannelListWidget> {
|
|||||||
final otherside =
|
final otherside =
|
||||||
item.members!.where((e) => e.account.id != widget.selfId).first;
|
item.members!.where((e) => e.account.id != widget.selfId).first;
|
||||||
|
|
||||||
|
final avatar = AccountAvatar(
|
||||||
|
content: otherside.account.avatar,
|
||||||
|
radius: widget.isDense ? 12 : 20,
|
||||||
|
bgColor: Theme.of(context).colorScheme.primary,
|
||||||
|
feColor: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (widget.isCollapsed) {
|
||||||
|
return Tooltip(
|
||||||
|
message: otherside.account.nick,
|
||||||
|
child: InkWell(
|
||||||
|
child: avatar.paddingSymmetric(vertical: 12),
|
||||||
|
onTap: () => _gotoChannel(item),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: AccountAvatar(
|
leading: avatar,
|
||||||
content: otherside.account.avatar,
|
|
||||||
radius: widget.isDense ? 12 : 20,
|
|
||||||
bgColor: Theme.of(context).colorScheme.primary,
|
|
||||||
feColor: Theme.of(context).colorScheme.onPrimary,
|
|
||||||
),
|
|
||||||
contentPadding: padding,
|
contentPadding: padding,
|
||||||
title: Text(otherside.account.nick),
|
title: Text(otherside.account.nick),
|
||||||
subtitle: !widget.isDense
|
subtitle: !widget.isDense
|
||||||
@@ -145,24 +159,42 @@ class _ChannelListWidgetState extends State<ChannelListWidget> {
|
|||||||
onTap: () => _gotoChannel(item),
|
onTap: () => _gotoChannel(item),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
final avatar = CircleAvatar(
|
||||||
|
backgroundColor: item.realmId == null
|
||||||
|
? Theme.of(context).colorScheme.primary
|
||||||
|
: Colors.transparent,
|
||||||
|
radius: widget.isDense ? 12 : 20,
|
||||||
|
child: FaIcon(
|
||||||
|
FontAwesomeIcons.hashtag,
|
||||||
|
color: item.realmId == null
|
||||||
|
? Theme.of(context).colorScheme.onPrimary
|
||||||
|
: Theme.of(context).colorScheme.primary,
|
||||||
|
size: widget.isDense ? 12 : 16,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (widget.isCollapsed) {
|
||||||
|
return Tooltip(
|
||||||
|
message: item.name,
|
||||||
|
child: InkWell(
|
||||||
|
child: avatar.paddingSymmetric(vertical: 12),
|
||||||
|
onTap: () => _gotoChannel(item),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
minTileHeight: widget.isDense ? 48 : null,
|
minTileHeight: widget.isDense ? 48 : null,
|
||||||
leading: CircleAvatar(
|
leading: avatar,
|
||||||
backgroundColor: item.realmId == null
|
|
||||||
? Theme.of(context).colorScheme.primary
|
|
||||||
: Colors.transparent,
|
|
||||||
radius: widget.isDense ? 12 : 20,
|
|
||||||
child: FaIcon(
|
|
||||||
FontAwesomeIcons.hashtag,
|
|
||||||
color: item.realmId == null
|
|
||||||
? Theme.of(context).colorScheme.onPrimary
|
|
||||||
: Theme.of(context).colorScheme.primary,
|
|
||||||
size: widget.isDense ? 12 : 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
contentPadding: padding,
|
contentPadding: padding,
|
||||||
title: Text(item.name),
|
title: Text(item.name),
|
||||||
subtitle: !widget.isDense ? Text(item.description) : null,
|
subtitle: !widget.isDense
|
||||||
|
? Text(
|
||||||
|
item.description,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
onTap: () => _gotoChannel(item),
|
onTap: () => _gotoChannel(item),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,9 +75,6 @@ class ChatEvent extends StatelessWidget {
|
|||||||
key: Key('m${item.uuid}attachments-box'),
|
key: Key('m${item.uuid}attachments-box'),
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
padding: EdgeInsets.only(top: isMerged ? 0 : 4, bottom: 4),
|
padding: EdgeInsets.only(top: isMerged ? 0 : 4, bottom: 4),
|
||||||
constraints: const BoxConstraints(
|
|
||||||
maxHeight: 720,
|
|
||||||
),
|
|
||||||
child: AttachmentList(
|
child: AttachmentList(
|
||||||
key: Key('m${item.uuid}attachments'),
|
key: Key('m${item.uuid}attachments'),
|
||||||
parentId: item.uuid,
|
parentId: item.uuid,
|
||||||
@@ -301,7 +298,10 @@ class ChatEvent extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
).paddingSymmetric(horizontal: 12),
|
).paddingSymmetric(horizontal: 12),
|
||||||
_buildLinkExpansion().paddingOnly(left: 52, right: 8),
|
_buildLinkExpansion().paddingOnly(left: 52, right: 8),
|
||||||
_buildAttachment(context).paddingOnly(left: 56, right: 8),
|
_buildAttachment(
|
||||||
|
context,
|
||||||
|
isMinimal: ['messages.edit'].contains(item.type),
|
||||||
|
).paddingOnly(left: 56, right: 8),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
_editTo = widget.edit!;
|
_editTo = widget.edit!;
|
||||||
_textController.text = body.text;
|
_textController.text = body.text;
|
||||||
_attachments.addAll(
|
_attachments.addAll(
|
||||||
widget.edit!.body['attachments']?.cast<int>() ?? List.empty());
|
widget.edit!.body['attachments']?.cast<String>() ?? List.empty(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (widget.reply != null) {
|
if (widget.reply != null) {
|
||||||
_replyTo = widget.reply!;
|
_replyTo = widget.reply!;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ abstract class AppNavigation {
|
|||||||
),
|
),
|
||||||
AppNavigationDestination(
|
AppNavigationDestination(
|
||||||
icon: Icons.forum,
|
icon: Icons.forum,
|
||||||
label: 'channelTypeDirect'.tr,
|
label: 'chat'.tr,
|
||||||
page: 'chat',
|
page: 'chat',
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -192,9 +192,9 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _autoResize() {
|
void _autoResize() {
|
||||||
if (SolianTheme.isExtraLargeScreen(context)) {
|
if (AppTheme.isExtraLargeScreen(context)) {
|
||||||
_expandDrawer();
|
_expandDrawer();
|
||||||
} else if (SolianTheme.isLargeScreen(context)) {
|
} else if (AppTheme.isLargeScreen(context)) {
|
||||||
_collapseDrawer();
|
_collapseDrawer();
|
||||||
} else {
|
} else {
|
||||||
_drawerAnimationController.value = 1;
|
_drawerAnimationController.value = 1;
|
||||||
@@ -229,7 +229,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer>
|
|||||||
return Drawer(
|
return Drawer(
|
||||||
width: _drawerAnimation.value,
|
width: _drawerAnimation.value,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
SolianTheme.isLargeScreen(context) ? Colors.transparent : null,
|
AppTheme.isLargeScreen(context) ? Colors.transparent : null,
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -239,80 +239,46 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer>
|
|||||||
children: [
|
children: [
|
||||||
_buildUserInfo().paddingSymmetric(vertical: 8),
|
_buildUserInfo().paddingSymmetric(vertical: 8),
|
||||||
const Divider(thickness: 0.3, height: 1),
|
const Divider(thickness: 0.3, height: 1),
|
||||||
Column(
|
SizedBox(
|
||||||
children: AppNavigation.destinations
|
width: double.infinity,
|
||||||
.map(
|
child: Wrap(
|
||||||
(e) => _isCollapsed
|
runSpacing: 8,
|
||||||
? Tooltip(
|
spacing: 8,
|
||||||
message: e.label,
|
alignment: WrapAlignment.spaceAround,
|
||||||
child: InkWell(
|
children: AppNavigation.destinations
|
||||||
child: Icon(e.icon, size: 20).paddingSymmetric(
|
.map(
|
||||||
horizontal: 28,
|
(e) => Tooltip(
|
||||||
vertical: 16,
|
message: e.label,
|
||||||
),
|
child: InkWell(
|
||||||
onTap: () {
|
borderRadius:
|
||||||
AppRouter.instance.goNamed(e.page);
|
const BorderRadius.all(Radius.circular(8)),
|
||||||
_closeDrawer();
|
child: Icon(
|
||||||
},
|
e.icon,
|
||||||
),
|
size: 22,
|
||||||
)
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
: ListTile(
|
).paddingAll(16),
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
onTap: () {
|
||||||
horizontal: 20,
|
AppRouter.instance.goNamed(e.page);
|
||||||
),
|
_closeDrawer();
|
||||||
leading: Icon(e.icon, size: 20).paddingAll(2),
|
},
|
||||||
title: !_isCollapsed ? Text(e.label) : null,
|
),
|
||||||
enabled: true,
|
),
|
||||||
onTap: () {
|
)
|
||||||
AppRouter.instance.goNamed(e.page);
|
.toList(),
|
||||||
_closeDrawer();
|
).paddingSymmetric(vertical: 8, horizontal: 12),
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
),
|
),
|
||||||
const Divider(thickness: 0.3, height: 1),
|
const Divider(thickness: 0.3, height: 1),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: AppNavigationRegion(
|
child: Material(
|
||||||
isCollapsed: _isCollapsed,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
onSelected: (item) {
|
child: AppNavigationRegion(
|
||||||
_closeDrawer();
|
isCollapsed: _isCollapsed,
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(thickness: 0.3, height: 1),
|
const Divider(thickness: 0.3, height: 1),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
if (_isCollapsed)
|
|
||||||
Tooltip(
|
|
||||||
message: 'settings'.tr,
|
|
||||||
child: InkWell(
|
|
||||||
child: const Icon(
|
|
||||||
Icons.settings,
|
|
||||||
size: 20,
|
|
||||||
).paddingSymmetric(
|
|
||||||
horizontal: 28,
|
|
||||||
vertical: 10,
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
AppRouter.instance.pushNamed('settings');
|
|
||||||
_closeDrawer();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
ListTile(
|
|
||||||
minTileHeight: 0,
|
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 20,
|
|
||||||
),
|
|
||||||
leading: const Icon(Icons.settings, size: 20).paddingAll(2),
|
|
||||||
title: Text('settings'.tr),
|
|
||||||
onTap: () {
|
|
||||||
AppRouter.instance.pushNamed('settings');
|
|
||||||
_closeDrawer();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (_isCollapsed)
|
if (_isCollapsed)
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: 'expand'.tr,
|
message: 'expand'.tr,
|
||||||
|
|||||||
@@ -1,48 +1,110 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:solian/models/channel.dart';
|
import 'package:solian/models/realm.dart';
|
||||||
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/providers/content/channel.dart';
|
import 'package:solian/providers/content/channel.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/providers/content/realm.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:solian/providers/navigation.dart';
|
||||||
|
import 'package:solian/widgets/account/account_avatar.dart';
|
||||||
|
import 'package:solian/widgets/channel/channel_list.dart';
|
||||||
|
|
||||||
class AppNavigationRegion extends StatelessWidget {
|
class AppNavigationRegion extends StatefulWidget {
|
||||||
final bool isCollapsed;
|
final bool isCollapsed;
|
||||||
final Function(Channel item) onSelected;
|
|
||||||
|
|
||||||
const AppNavigationRegion({
|
const AppNavigationRegion({
|
||||||
super.key,
|
super.key,
|
||||||
required this.onSelected,
|
|
||||||
this.isCollapsed = false,
|
this.isCollapsed = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
void _gotoChannel(Channel item) {
|
@override
|
||||||
AppRouter.instance.goNamed(
|
State<AppNavigationRegion> createState() => _AppNavigationRegionState();
|
||||||
'channelChat',
|
}
|
||||||
pathParameters: {'alias': item.alias},
|
|
||||||
queryParameters: {
|
|
||||||
if (item.realmId != null) 'realm': item.realm!.alias,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
onSelected(item);
|
class _AppNavigationRegionState extends State<AppNavigationRegion> {
|
||||||
|
bool _isTryingExit = false;
|
||||||
|
|
||||||
|
void _focusRealm(Realm item) {
|
||||||
|
setState(
|
||||||
|
() => Get.find<NavigationStateProvider>().focusedRealm.value = item,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEntry(BuildContext context, Channel item) {
|
void _unFocusRealm() {
|
||||||
const padding = EdgeInsets.symmetric(horizontal: 20);
|
setState(
|
||||||
|
() => Get.find<NavigationStateProvider>().focusedRealm.value = null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (isCollapsed) {
|
@override
|
||||||
return InkWell(
|
void dispose() {
|
||||||
child: const Icon(Icons.tag_outlined, size: 20).paddingSymmetric(
|
super.dispose();
|
||||||
horizontal: 20,
|
}
|
||||||
vertical: 16,
|
|
||||||
|
Widget _buildRealmFocusAvatar() {
|
||||||
|
final focusedRealm = Get.find<NavigationStateProvider>().focusedRealm.value;
|
||||||
|
return GestureDetector(
|
||||||
|
child: MouseRegion(
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
switchInCurve: Curves.fastOutSlowIn,
|
||||||
|
switchOutCurve: Curves.fastOutSlowIn,
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
transitionBuilder: (child, animation) {
|
||||||
|
return ScaleTransition(
|
||||||
|
scale: animation,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: _isTryingExit
|
||||||
|
? CircleAvatar(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
|
child: const Icon(
|
||||||
|
Icons.arrow_back,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
).paddingSymmetric(
|
||||||
|
vertical: 8,
|
||||||
|
)
|
||||||
|
: _buildEntryAvatar(focusedRealm!),
|
||||||
),
|
),
|
||||||
onTap: () => _gotoChannel(item),
|
onEnter: (_) => setState(() => _isTryingExit = true),
|
||||||
|
onExit: (_) => setState(() => _isTryingExit = false),
|
||||||
|
),
|
||||||
|
onTap: () => _unFocusRealm(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildEntryAvatar(Realm item) {
|
||||||
|
return Hero(
|
||||||
|
tag: Key('region-realm-avatar-${item.id}'),
|
||||||
|
child: (item.avatar?.isNotEmpty ?? false)
|
||||||
|
? AccountAvatar(content: item.avatar)
|
||||||
|
: CircleAvatar(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
|
child: const Icon(
|
||||||
|
Icons.workspaces,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
).paddingSymmetric(
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildEntry(BuildContext context, Realm item) {
|
||||||
|
const padding = EdgeInsets.symmetric(horizontal: 20, vertical: 8);
|
||||||
|
|
||||||
|
if (widget.isCollapsed) {
|
||||||
|
return InkWell(
|
||||||
|
child: _buildEntryAvatar(item).paddingSymmetric(vertical: 8),
|
||||||
|
onTap: () => _focusRealm(item),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
minTileHeight: 0,
|
minTileHeight: 0,
|
||||||
leading: const Icon(Icons.tag_outlined),
|
leading: _buildEntryAvatar(item),
|
||||||
contentPadding: padding,
|
contentPadding: padding,
|
||||||
title: Text(item.name),
|
title: Text(item.name),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
@@ -50,76 +112,104 @@ class AppNavigationRegion extends StatelessWidget {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
onTap: () => _gotoChannel(item),
|
onTap: () => _focusRealm(item),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final RealmProvider realms = Get.find();
|
||||||
final ChannelProvider channels = Get.find();
|
final ChannelProvider channels = Get.find();
|
||||||
|
final AuthProvider auth = Get.find();
|
||||||
|
final NavigationStateProvider navState = Get.find();
|
||||||
|
|
||||||
return Obx(() {
|
return Obx(
|
||||||
final List<Channel> noRealmGroupChannels = channels.availableChannels
|
() => AnimatedSwitcher(
|
||||||
.where((x) => x.type == 0 && x.realmId == null)
|
switchInCurve: Curves.fastOutSlowIn,
|
||||||
.toList();
|
switchOutCurve: Curves.fastOutSlowIn,
|
||||||
final List<Channel> hasRealmGroupChannels = channels.availableChannels
|
duration: const Duration(milliseconds: 300),
|
||||||
.where((x) => x.type == 0 && x.realmId != null)
|
transitionBuilder: (child, animation) {
|
||||||
.toList();
|
return SlideTransition(
|
||||||
|
position: Tween<Offset>(
|
||||||
if (isCollapsed) {
|
begin: const Offset(1.0, 0.0),
|
||||||
return CustomScrollView(
|
end: Offset.zero,
|
||||||
slivers: [
|
).animate(animation),
|
||||||
const SliverPadding(padding: EdgeInsets.only(top: 8)),
|
child: Material(
|
||||||
SliverList.builder(
|
color: Theme.of(context).colorScheme.surface,
|
||||||
itemCount:
|
child: child,
|
||||||
noRealmGroupChannels.length + hasRealmGroupChannels.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final element = index >= noRealmGroupChannels.length
|
|
||||||
? hasRealmGroupChannels[index - noRealmGroupChannels.length]
|
|
||||||
: noRealmGroupChannels[index];
|
|
||||||
return Tooltip(
|
|
||||||
message: element.name,
|
|
||||||
child: _buildEntry(context, element),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
);
|
},
|
||||||
}
|
child: navState.focusedRealm.value == null
|
||||||
|
? widget.isCollapsed
|
||||||
return CustomScrollView(
|
? CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
const SliverPadding(padding: EdgeInsets.only(top: 8)),
|
const SliverPadding(padding: EdgeInsets.only(top: 16)),
|
||||||
SliverList.builder(
|
SliverList.builder(
|
||||||
itemCount: noRealmGroupChannels.length,
|
itemCount: realms.availableRealms.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final element = noRealmGroupChannels[index];
|
final element = realms.availableRealms[index];
|
||||||
return _buildEntry(context, element);
|
return Tooltip(
|
||||||
},
|
message: element.name,
|
||||||
),
|
child: _buildEntry(context, element),
|
||||||
SliverList.list(
|
);
|
||||||
children: hasRealmGroupChannels
|
},
|
||||||
.groupListsBy((x) => x.realm)
|
),
|
||||||
.entries
|
],
|
||||||
.map((element) {
|
)
|
||||||
return ExpansionTile(
|
: CustomScrollView(
|
||||||
minTileHeight: 0,
|
slivers: [
|
||||||
initiallyExpanded: true,
|
SliverList.builder(
|
||||||
tilePadding: const EdgeInsets.only(left: 20, right: 24),
|
itemCount: realms.availableRealms.length,
|
||||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
|
itemBuilder: (context, index) {
|
||||||
collapsedBackgroundColor:
|
final element = realms.availableRealms[index];
|
||||||
Theme.of(context).colorScheme.surfaceContainer,
|
return _buildEntry(context, element);
|
||||||
title: Text(element.value.first.realm!.name),
|
},
|
||||||
leading: const Icon(Icons.workspaces, size: 16)
|
),
|
||||||
.paddingSymmetric(horizontal: 4),
|
],
|
||||||
children:
|
)
|
||||||
element.value.map((x) => _buildEntry(context, x)).toList(),
|
: Column(
|
||||||
);
|
children: [
|
||||||
}).toList(),
|
if (widget.isCollapsed)
|
||||||
),
|
Tooltip(
|
||||||
const SliverPadding(padding: EdgeInsets.only(bottom: 8)),
|
message: navState.focusedRealm.value!.name,
|
||||||
],
|
child: _buildRealmFocusAvatar().paddingOnly(
|
||||||
);
|
top: 24,
|
||||||
});
|
bottom: 8,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ListTile(
|
||||||
|
minTileHeight: 0,
|
||||||
|
tileColor:
|
||||||
|
Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
|
leading: _buildRealmFocusAvatar(),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20, vertical: 8),
|
||||||
|
title: Text(navState.focusedRealm.value!.name),
|
||||||
|
subtitle: Text(
|
||||||
|
navState.focusedRealm.value!.description,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Obx(
|
||||||
|
() => ChannelListWidget(
|
||||||
|
useReplace: true,
|
||||||
|
channels: channels.availableChannels
|
||||||
|
.where((x) =>
|
||||||
|
x.realm?.id == navState.focusedRealm.value?.id)
|
||||||
|
.toList(),
|
||||||
|
isCollapsed: widget.isCollapsed,
|
||||||
|
selfId: auth.userProfile.value!['id'],
|
||||||
|
noCategory: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:solian/models/post.dart';
|
import 'package:solian/models/post.dart';
|
||||||
import 'package:solian/screens/posts/post_detail.dart';
|
import 'package:solian/screens/posts/post_detail.dart';
|
||||||
import 'package:solian/shells/title_shell.dart';
|
import 'package:solian/shells/title_shell.dart';
|
||||||
|
import 'package:solian/theme.dart';
|
||||||
import 'package:solian/widgets/account/account_avatar.dart';
|
import 'package:solian/widgets/account/account_avatar.dart';
|
||||||
import 'package:solian/widgets/account/account_profile_popup.dart';
|
import 'package:solian/widgets/account/account_profile_popup.dart';
|
||||||
import 'package:solian/widgets/attachments/attachment_list.dart';
|
import 'package:solian/widgets/attachments/attachment_list.dart';
|
||||||
@@ -302,7 +303,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
autoload: false,
|
autoload: false,
|
||||||
isGrid: true,
|
isGrid: true,
|
||||||
).paddingOnly(left: 36, top: 4, bottom: 4);
|
).paddingOnly(left: 36, top: 4, bottom: 4);
|
||||||
} else if (attachments.length > 1) {
|
} else if (attachments.length > 1 || AppTheme.isLargeScreen(context)) {
|
||||||
return AttachmentList(
|
return AttachmentList(
|
||||||
parentId: widget.item.id.toString(),
|
parentId: widget.item.id.toString(),
|
||||||
attachmentsId: attachments,
|
attachmentsId: attachments,
|
||||||
@@ -497,7 +498,10 @@ class _PostItemState extends State<PostItem> {
|
|||||||
],
|
],
|
||||||
).paddingOnly(
|
).paddingOnly(
|
||||||
top: 10,
|
top: 10,
|
||||||
bottom: attachments.length == 1 ? 10 : 0,
|
bottom:
|
||||||
|
(attachments.length == 1 && !AppTheme.isLargeScreen(context))
|
||||||
|
? 10
|
||||||
|
: 0,
|
||||||
right: 16,
|
right: 16,
|
||||||
left: 16,
|
left: 16,
|
||||||
),
|
),
|
||||||
@@ -514,8 +518,13 @@ class _PostItemState extends State<PostItem> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
).paddingOnly(
|
).paddingOnly(
|
||||||
top: attachments.length == 1 ? 10 : 6,
|
top: (attachments.length == 1 && !AppTheme.isLargeScreen(context))
|
||||||
left: attachments.length == 1 ? 24 : 60,
|
? 10
|
||||||
|
: 6,
|
||||||
|
left:
|
||||||
|
(attachments.length == 1 && !AppTheme.isLargeScreen(context))
|
||||||
|
? 24
|
||||||
|
: 60,
|
||||||
right: 16,
|
right: 16,
|
||||||
bottom: 10,
|
bottom: 10,
|
||||||
)
|
)
|
||||||
|
|||||||
52
pubspec.lock
52
pubspec.lock
@@ -13,10 +13,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _flutterfire_internals
|
name: _flutterfire_internals
|
||||||
sha256: "9371d13b8ee442e3bfc08a24e3a1b3742c839abbfaf5eef11b79c4b862c89bf7"
|
sha256: ddc6f775260b89176d329dee26f88b9469ef46aa3228ff6a0b91caf2b2989692
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.41"
|
version: "1.3.42"
|
||||||
_macros:
|
_macros:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: dart
|
description: dart
|
||||||
@@ -306,10 +306,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dart_webrtc
|
name: dart_webrtc
|
||||||
sha256: ac7ef077084b3e54004716f1d736fcd839e1b60bc3f21f4122a35a9bb5ca2e47
|
sha256: c664ad88d5646735753add421ee2118486c100febef5e92b7f59cdbabf6a51f6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.8"
|
version: "1.4.9"
|
||||||
dbus:
|
dbus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -426,10 +426,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: file_picker
|
name: file_picker
|
||||||
sha256: "825aec673606875c33cd8d3c4083f1a3c3999015a84178b317b7ef396b7384f3"
|
sha256: "167bb619cdddaa10ef2907609feb8a79c16dfa479d3afaf960f8e223f754bf12"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.0.7"
|
version: "8.1.2"
|
||||||
file_selector_linux:
|
file_selector_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -490,10 +490,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
sha256: "06537da27db981947fa535bb91ca120b4e9cb59cb87278dbdde718558cafc9ff"
|
sha256: "40921de9795fbf5887ed5c0adfdf4972d5a8d7ae7e1b2bb98dea39bc02626a88"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.0"
|
version: "3.4.1"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -506,10 +506,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_web
|
name: firebase_core_web
|
||||||
sha256: "362e52457ed2b7b180964769c1e04d1e0ea0259fdf7025fdfedd019d4ae2bd88"
|
sha256: f4ee170441ca141c5f9ee5ad8737daba3ee9c8e7efb6902aee90b4fbd178ce25
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.17.5"
|
version: "2.18.0"
|
||||||
firebase_crashlytics:
|
firebase_crashlytics:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -538,18 +538,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_platform_interface
|
name: firebase_messaging_platform_interface
|
||||||
sha256: "26c5370d3a79b15c8032724a68a4741e28f63e1f1a45699c4f0a8ae740aadd72"
|
sha256: d8a4984635f09213302243ea670fe5c42f3261d7d8c7c0a5f7dcd5d6c84be459
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.5.43"
|
version: "4.5.44"
|
||||||
firebase_messaging_web:
|
firebase_messaging_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_web
|
name: firebase_messaging_web
|
||||||
sha256: "58276cd5d9e22a9320ef9e5bc358628920f770f93c91221f8b638e8346ed5df4"
|
sha256: "258b9d637965db7855299b123533609ed95e52350746a723dfd1d8d6f3fac678"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.8.13"
|
version: "3.9.0"
|
||||||
firebase_performance:
|
firebase_performance:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -849,10 +849,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_webrtc
|
name: flutter_webrtc
|
||||||
sha256: "67faa07cf49392b50b1aa14590a83caa64d2109345fabd29899dcd8da8538348"
|
sha256: f6800cc2af79018c12e955ddf8ad007891fdfbb8199b0ce3dccd0977ed2add9c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.11.6+hotfix.1"
|
version: "0.11.7"
|
||||||
font_awesome_flutter:
|
font_awesome_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1169,10 +1169,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: livekit_client
|
name: livekit_client
|
||||||
sha256: fc86a8b65b74b41faef646cc671c1892a457c24fd69910e25f7a50dc8cdd3155
|
sha256: "5df9b6f153b5f2c59fbf116b41e54597dfe8b2340b6630f7d8869887a9e58f44"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.4"
|
version: "2.2.5"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1369,10 +1369,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: pasteboard
|
name: pasteboard
|
||||||
sha256: "1c8b6a8b3f1d12e55d4e9404433cda1b4abe66db6b17bc2d2fb5965772c04674"
|
sha256: "7bf733f3a00c7188ec1f2c6f0612854248b302cf91ef3611a2b7bb141c0f9d55"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.3.0"
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1721,10 +1721,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share_plus
|
name: share_plus
|
||||||
sha256: "59dfd53f497340a0c3a81909b220cfdb9b8973a91055c4e5ab9b9b9ad7c513c0"
|
sha256: "468c43f285207c84bcabf5737f33b914ceb8eb38398b91e5e3ad1698d1b72a52"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.0"
|
version: "10.0.2"
|
||||||
share_plus_platform_interface:
|
share_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1886,10 +1886,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqlite3
|
name: sqlite3
|
||||||
sha256: fde692580bee3379374af1f624eb3e113ab2865ecb161dbe2d8ac2de9735dbdb
|
sha256: "45f168ae2213201b54e09429ed0c593dc2c88c924a1488d6f9c523a255d567cb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.5"
|
version: "2.4.6"
|
||||||
sqlparser:
|
sqlparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2166,10 +2166,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: web
|
name: web
|
||||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.1"
|
version: "1.0.0"
|
||||||
web_socket:
|
web_socket:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: solian
|
|||||||
description: "The Solar Network App"
|
description: "The Solar Network App"
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.2.1+35
|
version: 1.2.1+36
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.4 <4.0.0"
|
sdk: ">=3.3.4 <4.0.0"
|
||||||
@@ -44,7 +44,7 @@ dependencies:
|
|||||||
sqflite: ^2.3.3+1
|
sqflite: ^2.3.3+1
|
||||||
protocol_handler: ^0.2.0
|
protocol_handler: ^0.2.0
|
||||||
markdown: ^7.2.2
|
markdown: ^7.2.2
|
||||||
pasteboard: ^0.2.0
|
pasteboard: ^0.3.0
|
||||||
desktop_drop: ^0.4.4
|
desktop_drop: ^0.4.4
|
||||||
badges: ^3.1.2
|
badges: ^3.1.2
|
||||||
flutter_card_swiper: ^7.0.1
|
flutter_card_swiper: ^7.0.1
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
|
|
||||||
|
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
|
||||||
<style id="splash-screen-style">
|
<style id="splash-screen-style">
|
||||||
html {
|
html {
|
||||||
height: 100%
|
height: 100%
|
||||||
|
|||||||
Reference in New Issue
Block a user