Compare commits
6 Commits
0ad4854443
...
1.2.0+9
| Author | SHA1 | Date | |
|---|---|---|---|
| 989b5babd9 | |||
| 9ea364640d | |||
| a9f55a489d | |||
| 4616f3a3e2 | |||
| 425bae9d13 | |||
| 07771e8979 |
@@ -1,8 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_animate/flutter_animate.dart';
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:solian/exts.dart';
|
import 'package:solian/exts.dart';
|
||||||
|
import 'package:solian/platform.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/providers/content/channel.dart';
|
import 'package:solian/providers/content/channel.dart';
|
||||||
import 'package:solian/providers/content/realm.dart';
|
import 'package:solian/providers/content/realm.dart';
|
||||||
@@ -24,6 +26,7 @@ class BootstrapperShell extends StatefulWidget {
|
|||||||
class _BootstrapperShellState extends State<BootstrapperShell> {
|
class _BootstrapperShellState extends State<BootstrapperShell> {
|
||||||
bool _isBusy = true;
|
bool _isBusy = true;
|
||||||
bool _isErrored = false;
|
bool _isErrored = false;
|
||||||
|
bool _isDismissable = true;
|
||||||
String? _subtitle;
|
String? _subtitle;
|
||||||
|
|
||||||
Color get _unFocusColor =>
|
Color get _unFocusColor =>
|
||||||
@@ -38,6 +41,32 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
await context.read<ThemeSwitcher>().restoreTheme();
|
await context.read<ThemeSwitcher>().restoreTheme();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
label: 'bsCheckForUpdate',
|
||||||
|
action: () async {
|
||||||
|
if (PlatformInfo.isWeb) return;
|
||||||
|
try {
|
||||||
|
final info = await PackageInfo.fromPlatform();
|
||||||
|
final localVersionString = '${info.version}+${info.buildNumber}';
|
||||||
|
final resp = await GetConnect().get(
|
||||||
|
'https://git.solsynth.dev/api/v1/repos/hydrogen/solian/tags?limit=1',
|
||||||
|
);
|
||||||
|
if (resp.body[0]['name'] != localVersionString) {
|
||||||
|
setState(() {
|
||||||
|
_isErrored = true;
|
||||||
|
_subtitle = PlatformInfo.isIOS || PlatformInfo.isMacOS
|
||||||
|
? 'bsCheckForUpdateDescApple'.tr
|
||||||
|
: 'bsCheckForUpdateDescCommon'.tr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
_isErrored = true;
|
||||||
|
_subtitle = 'bsCheckForUpdateFailed'.tr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
label: 'bsCheckingServer',
|
label: 'bsCheckingServer',
|
||||||
action: () async {
|
action: () async {
|
||||||
@@ -47,12 +76,14 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_isErrored = true;
|
_isErrored = true;
|
||||||
_subtitle = 'bsCheckingServerDown'.tr;
|
_subtitle = 'bsCheckingServerDown'.tr;
|
||||||
|
_isDismissable = false;
|
||||||
});
|
});
|
||||||
throw Exception('unable connect to server');
|
throw Exception('unable connect to server');
|
||||||
} else if (resp.statusCode == null) {
|
} else if (resp.statusCode == null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isErrored = true;
|
_isErrored = true;
|
||||||
_subtitle = 'bsCheckingServerFail'.tr;
|
_subtitle = 'bsCheckingServerFail'.tr;
|
||||||
|
_isDismissable = false;
|
||||||
});
|
});
|
||||||
throw Exception('unable connect to server');
|
throw Exception('unable connect to server');
|
||||||
}
|
}
|
||||||
@@ -85,7 +116,7 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
await Future.wait([
|
await Future.wait([
|
||||||
Get.find<RealmProvider>().refreshAvailableRealms(),
|
Get.find<RealmProvider>().refreshAvailableRealms(),
|
||||||
Get.find<ChannelProvider>().refreshAvailableChannel(),
|
Get.find<ChannelProvider>().refreshAvailableChannel(),
|
||||||
Get.find<RelationshipProvider>().refreshFriendList(),
|
Get.find<RelationshipProvider>().refreshRelativeList(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -148,9 +179,11 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (_isErrored)
|
if (_isErrored && !_isDismissable)
|
||||||
const Icon(Icons.cancel, size: 24)
|
const Icon(Icons.cancel, size: 24),
|
||||||
else
|
if (_isErrored && _isDismissable)
|
||||||
|
const Icon(Icons.warning, size: 24),
|
||||||
|
if (!_isErrored && _isBusy)
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
@@ -161,15 +194,24 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
if (_subtitle == null)
|
||||||
_subtitle ??
|
Text(
|
||||||
'${_periods[_periodCursor].label.tr} (${_periodCursor + 1}/${_periods.length})',
|
'${_periods[_periodCursor].label.tr} (${_periodCursor + 1}/${_periods.length})',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
color: _unFocusColor,
|
color: _unFocusColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
if (_subtitle != null)
|
||||||
|
Text(
|
||||||
|
_subtitle!,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: _unFocusColor,
|
||||||
|
),
|
||||||
|
).paddingOnly(bottom: 4),
|
||||||
Text(
|
Text(
|
||||||
'2024 © Solsynth LLC',
|
'2024 © Solsynth LLC',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
@@ -185,12 +227,19 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (_isBusy) return;
|
if (_isBusy) return;
|
||||||
setState(() {
|
if (_isDismissable) {
|
||||||
_isBusy = true;
|
setState(() {
|
||||||
_isErrored = false;
|
_isBusy = false;
|
||||||
_periodCursor = 0;
|
_isErrored = false;
|
||||||
});
|
});
|
||||||
_runPeriods();
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_isBusy = true;
|
||||||
|
_isErrored = false;
|
||||||
|
_periodCursor = 0;
|
||||||
|
});
|
||||||
|
_runPeriods();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -30,6 +30,23 @@ extension SolianExtenions on BuildContext {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> showInfoDialog(String title, body) {
|
||||||
|
return showDialog<void>(
|
||||||
|
useRootNavigator: true,
|
||||||
|
context: this,
|
||||||
|
builder: (ctx) => AlertDialog(
|
||||||
|
title: Text(title),
|
||||||
|
content: Text(body),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(ctx),
|
||||||
|
child: Text('okay'.tr),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> showErrorDialog(dynamic exception) {
|
Future<void> showErrorDialog(dynamic exception) {
|
||||||
var stack = StackTrace.current;
|
var stack = StackTrace.current;
|
||||||
var stackTrace = '$stack';
|
var stackTrace = '$stack';
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:get/get_rx/get_rx.dart';
|
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:solian/models/call.dart';
|
import 'package:solian/models/call.dart';
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'dart:typed_data';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:solian/models/attachment.dart';
|
import 'package:solian/models/attachment.dart';
|
||||||
|
import 'package:solian/models/pagination.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/services.dart';
|
import 'package:solian/services.dart';
|
||||||
import 'package:dio/dio.dart' as dio;
|
import 'package:dio/dio.dart' as dio;
|
||||||
@@ -21,6 +22,48 @@ class AttachmentProvider extends GetConnect {
|
|||||||
|
|
||||||
final Map<int, Attachment> _cachedResponses = {};
|
final Map<int, Attachment> _cachedResponses = {};
|
||||||
|
|
||||||
|
Future<List<Attachment?>> listMetadata(
|
||||||
|
List<int> id, {
|
||||||
|
noCache = false,
|
||||||
|
}) async {
|
||||||
|
List<Attachment?> result = List.filled(id.length, null);
|
||||||
|
List<int> pendingQuery = List.empty(growable: true);
|
||||||
|
if (!noCache) {
|
||||||
|
for (var idx = 0; idx < id.length; idx++) {
|
||||||
|
if (_cachedResponses.containsKey(id[idx])) {
|
||||||
|
result[idx] = _cachedResponses[id[idx]];
|
||||||
|
} else {
|
||||||
|
pendingQuery.add(id[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final resp = await get(
|
||||||
|
'/attachments?take=${pendingQuery.length}&id=${pendingQuery.join(',')}',
|
||||||
|
);
|
||||||
|
if (resp.statusCode != 200) return result;
|
||||||
|
|
||||||
|
final rawOut = PaginationResult.fromJson(resp.body);
|
||||||
|
if (rawOut.data == null) return result;
|
||||||
|
|
||||||
|
final List<Attachment> out =
|
||||||
|
rawOut.data!.map((x) => Attachment.fromJson(x)).toList();
|
||||||
|
for (final item in out) {
|
||||||
|
if (item.destination != 0 && item.isAnalyzed) {
|
||||||
|
_cachedResponses[item.id] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < out.length; i++) {
|
||||||
|
for (var j = 0; j < id.length; j++) {
|
||||||
|
if (out[i].id == id[j]) {
|
||||||
|
result[j] = out[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Attachment?> getMetadata(int id, {noCache = false}) async {
|
Future<Attachment?> getMetadata(int id, {noCache = false}) async {
|
||||||
if (!noCache && _cachedResponses.containsKey(id)) {
|
if (!noCache && _cachedResponses.containsKey(id)) {
|
||||||
return _cachedResponses[id]!;
|
return _cachedResponses[id]!;
|
||||||
|
|||||||
@@ -4,15 +4,19 @@ import 'package:solian/models/relations.dart';
|
|||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
|
|
||||||
class RelationshipProvider extends GetxController {
|
class RelationshipProvider extends GetxController {
|
||||||
|
final RxInt friendRequestCount = 0.obs;
|
||||||
|
|
||||||
final RxList<Relationship> _friends = RxList.empty(growable: true);
|
final RxList<Relationship> _friends = RxList.empty(growable: true);
|
||||||
|
|
||||||
Future<void> refreshFriendList() async {
|
Future<void> refreshRelativeList() async {
|
||||||
final resp = await listRelationWithStatus(1);
|
final resp = await listRelation();
|
||||||
_friends.value = resp.body
|
final List<Relationship> result = resp.body
|
||||||
.map((e) => Relationship.fromJson(e))
|
.map((e) => Relationship.fromJson(e))
|
||||||
.toList()
|
.toList()
|
||||||
.cast<Relationship>();
|
.cast<Relationship>();
|
||||||
|
_friends.value = result.where((x) => x.status == 1).toList();
|
||||||
_friends.refresh();
|
_friends.refresh();
|
||||||
|
friendRequestCount.value = result.where((x) => x.status == 0).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasFriend(Account account) {
|
bool hasFriend(Account account) {
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ 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';
|
||||||
import 'package:solian/providers/account_status.dart';
|
import 'package:solian/providers/account_status.dart';
|
||||||
|
import 'package:solian/providers/relation.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/screens/auth/signin.dart';
|
import 'package:solian/screens/auth/signin.dart';
|
||||||
import 'package:solian/screens/auth/signup.dart';
|
import 'package:solian/screens/auth/signup.dart';
|
||||||
import 'package:solian/widgets/account/account_heading.dart';
|
import 'package:solian/widgets/account/account_heading.dart';
|
||||||
import 'package:solian/widgets/sized_container.dart';
|
import 'package:solian/widgets/sized_container.dart';
|
||||||
|
import 'package:badges/badges.dart' as badges;
|
||||||
|
|
||||||
class AccountScreen extends StatefulWidget {
|
class AccountScreen extends StatefulWidget {
|
||||||
const AccountScreen({super.key});
|
const AccountScreen({super.key});
|
||||||
@@ -23,9 +25,27 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||||||
(
|
(
|
||||||
const Icon(Icons.color_lens),
|
const Icon(Icons.color_lens),
|
||||||
'accountPersonalize'.tr,
|
'accountPersonalize'.tr,
|
||||||
'accountPersonalize'
|
'accountPersonalize',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Obx(() {
|
||||||
|
final RelationshipProvider relations = Get.find();
|
||||||
|
return badges.Badge(
|
||||||
|
badgeContent: Text(
|
||||||
|
relations.friendRequestCount.value.toString(),
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
showBadge: relations.friendRequestCount.value > 0,
|
||||||
|
position: badges.BadgePosition.topEnd(
|
||||||
|
top: -12,
|
||||||
|
end: -8,
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.diversity_1),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
'accountFriend'.tr,
|
||||||
|
'accountFriend',
|
||||||
),
|
),
|
||||||
(const Icon(Icons.diversity_1), 'accountFriend'.tr, 'accountFriend'),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_animate/flutter_animate.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:solian/exts.dart';
|
import 'package:solian/exts.dart';
|
||||||
import 'package:solian/models/relations.dart';
|
import 'package:solian/models/relations.dart';
|
||||||
import 'package:solian/providers/relation.dart';
|
import 'package:solian/providers/relation.dart';
|
||||||
|
import 'package:solian/theme.dart';
|
||||||
import 'package:solian/widgets/account/relative_list.dart';
|
import 'package:solian/widgets/account/relative_list.dart';
|
||||||
|
|
||||||
class FriendScreen extends StatefulWidget {
|
class FriendScreen extends StatefulWidget {
|
||||||
@@ -21,15 +21,15 @@ class _FriendScreenState extends State<FriendScreen>
|
|||||||
|
|
||||||
List<Relationship> _relations = List.empty();
|
List<Relationship> _relations = List.empty();
|
||||||
|
|
||||||
List<Relationship> filterByStatus(int status) {
|
List<Relationship> _filterByStatus(int status) {
|
||||||
return _relations.where((x) => x.status == status).toList();
|
return _relations.where((x) => x.status == status).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadRelations() async {
|
Future<void> _loadRelations() async {
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
final RelationshipProvider provider = Get.find();
|
final RelationshipProvider relations = Get.find();
|
||||||
final resp = await provider.listRelation();
|
final resp = await relations.listRelation();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_relations = resp.body
|
_relations = resp.body
|
||||||
@@ -38,6 +38,9 @@ class _FriendScreenState extends State<FriendScreen>
|
|||||||
.cast<Relationship>();
|
.cast<Relationship>();
|
||||||
_isBusy = false;
|
_isBusy = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
relations.friendRequestCount.value =
|
||||||
|
_relations.where((x) => x.status == 0).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void promptAddFriend() async {
|
void promptAddFriend() async {
|
||||||
@@ -104,8 +107,8 @@ class _FriendScreenState extends State<FriendScreen>
|
|||||||
super.initState();
|
super.initState();
|
||||||
_tabController = TabController(length: 3, vsync: this);
|
_tabController = TabController(length: 3, vsync: this);
|
||||||
|
|
||||||
loadRelations().then((_) {
|
_loadRelations().then((_) {
|
||||||
if (filterByStatus(0).isEmpty) {
|
if (_filterByStatus(0).isEmpty) {
|
||||||
_tabController.animateTo(1);
|
_tabController.animateTo(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -119,6 +122,19 @@ class _FriendScreenState extends State<FriendScreen>
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: Text('accountFriend'.tr),
|
title: Text('accountFriend'.tr),
|
||||||
|
actions: [
|
||||||
|
if (_isBusy)
|
||||||
|
SizedBox(
|
||||||
|
height: 48,
|
||||||
|
width: 48,
|
||||||
|
child: const CircularProgressIndicator(
|
||||||
|
strokeWidth: 3,
|
||||||
|
).paddingAll(14),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
||||||
|
),
|
||||||
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
tabs: const [
|
tabs: const [
|
||||||
@@ -136,46 +152,34 @@ class _FriendScreenState extends State<FriendScreen>
|
|||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
children: [
|
children: [
|
||||||
RefreshIndicator(
|
RefreshIndicator(
|
||||||
onRefresh: () => loadRelations(),
|
onRefresh: () => _loadRelations(),
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
if (_isBusy)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: const LinearProgressIndicator().animate().scaleX(),
|
|
||||||
),
|
|
||||||
SilverRelativeList(
|
SilverRelativeList(
|
||||||
items: filterByStatus(0),
|
items: _filterByStatus(0),
|
||||||
onUpdate: () => loadRelations(),
|
onUpdate: () => _loadRelations(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
RefreshIndicator(
|
RefreshIndicator(
|
||||||
onRefresh: () => loadRelations(),
|
onRefresh: () => _loadRelations(),
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
if (_isBusy)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: const LinearProgressIndicator().animate().scaleX(),
|
|
||||||
),
|
|
||||||
SilverRelativeList(
|
SilverRelativeList(
|
||||||
items: filterByStatus(1),
|
items: _filterByStatus(1),
|
||||||
onUpdate: () => loadRelations(),
|
onUpdate: () => _loadRelations(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
RefreshIndicator(
|
RefreshIndicator(
|
||||||
onRefresh: () => loadRelations(),
|
onRefresh: () => _loadRelations(),
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
if (_isBusy)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: const LinearProgressIndicator().animate().scaleX(),
|
|
||||||
),
|
|
||||||
SilverRelativeList(
|
SilverRelativeList(
|
||||||
items: filterByStatus(3),
|
items: _filterByStatus(3),
|
||||||
onUpdate: () => loadRelations(),
|
onUpdate: () => _loadRelations(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -314,6 +314,11 @@ const i18nEnglish = {
|
|||||||
'accountStatusNeutral': 'Neutral',
|
'accountStatusNeutral': 'Neutral',
|
||||||
'accountStatusPositive': 'Positive',
|
'accountStatusPositive': 'Positive',
|
||||||
'bsLoadingTheme': 'Loading Theme',
|
'bsLoadingTheme': 'Loading Theme',
|
||||||
|
'bsCheckForUpdate': 'Checking For Updates',
|
||||||
|
'bsCheckForUpdateFailed': 'Unable to Check Updates',
|
||||||
|
'bsCheckForUpdateNew': 'Found New Version',
|
||||||
|
'bsCheckForUpdateDescApple': 'Please head to TestFlight and update your app to latest version to prevent error happens and get latest functions.',
|
||||||
|
'bsCheckForUpdateDescCommon': 'Please head to our website download and install latest version of application to prevent error happens and get latest functions.',
|
||||||
'bsCheckingServer': 'Checking Server Status',
|
'bsCheckingServer': 'Checking Server Status',
|
||||||
'bsCheckingServerFail':
|
'bsCheckingServerFail':
|
||||||
'Unable connect to server, check your network connection',
|
'Unable connect to server, check your network connection',
|
||||||
|
|||||||
@@ -293,6 +293,11 @@ const i18nSimplifiedChinese = {
|
|||||||
'accountStatusNeutral': '中性',
|
'accountStatusNeutral': '中性',
|
||||||
'accountStatusPositive': '积极',
|
'accountStatusPositive': '积极',
|
||||||
'bsLoadingTheme': '正在装载主题',
|
'bsLoadingTheme': '正在装载主题',
|
||||||
|
'bsCheckForUpdate': '正在检查更新',
|
||||||
|
'bsCheckForUpdateFailed': '无法检查更新',
|
||||||
|
'bsCheckForUpdateNew': '发现新版本',
|
||||||
|
'bsCheckForUpdateDescApple': '请前往 TestFlight 并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。',
|
||||||
|
'bsCheckForUpdateDescCommon': '请前往我们的网站下载并安装最新版本的应用程序,以防止出现错误并获取最新功能。',
|
||||||
'bsCheckingServer': '检查服务器状态中',
|
'bsCheckingServer': '检查服务器状态中',
|
||||||
'bsCheckingServerFail': '无法连接至服务器,请检查你的网络连接状态',
|
'bsCheckingServerFail': '无法连接至服务器,请检查你的网络连接状态',
|
||||||
'bsCheckingServerDown': '当前服务器不可用,请稍后重试',
|
'bsCheckingServerDown': '当前服务器不可用,请稍后重试',
|
||||||
|
|||||||
@@ -222,19 +222,13 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
|
|||||||
|
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
int progress = 0;
|
attach.listMetadata(widget.initialAttachments).then((result) {
|
||||||
for (var idx = 0; idx < widget.initialAttachments.length; idx++) {
|
setState(() {
|
||||||
attach.getMetadata(widget.initialAttachments[idx]).then((resp) {
|
_attachments = result;
|
||||||
progress++;
|
_isBusy = false;
|
||||||
_attachments[idx] = resp;
|
_isFirstTimeBusy = false;
|
||||||
if (progress == widget.initialAttachments.length) {
|
|
||||||
setState(() {
|
|
||||||
_isBusy = false;
|
|
||||||
_isFirstTimeBusy = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showAttachmentPreview(Attachment element) {
|
void _showAttachmentPreview(Attachment element) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
List<Attachment?> _attachmentsMeta = List.empty();
|
List<Attachment?> _attachmentsMeta = List.empty();
|
||||||
|
|
||||||
void _getMetadataList() {
|
void _getMetadataList() {
|
||||||
final AttachmentProvider provider = Get.find();
|
final AttachmentProvider attach = Get.find();
|
||||||
|
|
||||||
if (widget.attachmentsId.isEmpty) {
|
if (widget.attachmentsId.isEmpty) {
|
||||||
return;
|
return;
|
||||||
@@ -53,25 +53,16 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
_attachmentsMeta = List.filled(widget.attachmentsId.length, null);
|
_attachmentsMeta = List.filled(widget.attachmentsId.length, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
int progress = 0;
|
attach.listMetadata(widget.attachmentsId).then((result) {
|
||||||
for (var idx = 0; idx < widget.attachmentsId.length; idx++) {
|
setState(() {
|
||||||
provider.getMetadata(widget.attachmentsId[idx]).then((resp) {
|
_attachmentsMeta = result;
|
||||||
progress++;
|
_isLoading = false;
|
||||||
if (resp != null) {
|
|
||||||
_attachmentsMeta[idx] = resp;
|
|
||||||
}
|
|
||||||
if (progress == widget.attachmentsId.length) {
|
|
||||||
calculateAspectRatio();
|
|
||||||
|
|
||||||
if (mounted) {
|
|
||||||
setState(() => _isLoading = false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
_calculateAspectRatio();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateAspectRatio() {
|
void _calculateAspectRatio() {
|
||||||
bool isConsistent = true;
|
bool isConsistent = true;
|
||||||
double? consistentValue;
|
double? consistentValue;
|
||||||
int portrait = 0, square = 0, landscape = 0;
|
int portrait = 0, square = 0, landscape = 0;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:solian/models/account_status.dart';
|
|||||||
import 'package:solian/providers/account_status.dart';
|
import 'package:solian/providers/account_status.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/providers/content/channel.dart';
|
import 'package:solian/providers/content/channel.dart';
|
||||||
|
import 'package:solian/providers/relation.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
import 'package:solian/shells/root_shell.dart';
|
import 'package:solian/shells/root_shell.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
@@ -60,8 +61,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
|||||||
AppRouter.instance.pushNamed('settings');
|
AppRouter.instance.pushNamed('settings');
|
||||||
setState(() => _selectedIndex = null);
|
setState(() => _selectedIndex = null);
|
||||||
_closeDrawer();
|
_closeDrawer();
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -130,22 +130,36 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
leading: Builder(builder: (context) {
|
leading: Obx(() {
|
||||||
final badgeColor = _accountStatus != null
|
final statusBadgeColor = _accountStatus != null
|
||||||
? StatusProvider.determineStatus(
|
? StatusProvider.determineStatus(
|
||||||
_accountStatus!,
|
_accountStatus!,
|
||||||
).$2
|
).$2
|
||||||
: Colors.grey;
|
: Colors.grey;
|
||||||
|
|
||||||
|
final RelationshipProvider relations = Get.find();
|
||||||
|
final accountNotifications = relations.friendRequestCount.value;
|
||||||
|
|
||||||
return badges.Badge(
|
return badges.Badge(
|
||||||
showBadge: _accountStatus != null,
|
badgeContent: Text(
|
||||||
badgeStyle: badges.BadgeStyle(badgeColor: badgeColor),
|
accountNotifications.toString(),
|
||||||
position: badges.BadgePosition.bottomEnd(
|
style: const TextStyle(color: Colors.white),
|
||||||
bottom: 0,
|
|
||||||
end: -2,
|
|
||||||
),
|
),
|
||||||
child: AccountAvatar(
|
showBadge: accountNotifications > 0,
|
||||||
content: auth.userProfile.value!['avatar'],
|
position: badges.BadgePosition.topEnd(
|
||||||
|
top: -10,
|
||||||
|
end: -6,
|
||||||
|
),
|
||||||
|
child: badges.Badge(
|
||||||
|
showBadge: _accountStatus != null,
|
||||||
|
badgeStyle: badges.BadgeStyle(badgeColor: statusBadgeColor),
|
||||||
|
position: badges.BadgePosition.bottomEnd(
|
||||||
|
bottom: 0,
|
||||||
|
end: -2,
|
||||||
|
),
|
||||||
|
child: AccountAvatar(
|
||||||
|
content: auth.userProfile.value!['avatar'],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|||||||
22
pubspec.lock
22
pubspec.lock
@@ -317,10 +317,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dev_build
|
name: dev_build
|
||||||
sha256: "76dd5b2587a891ab9c1e7f7eea6ca4a3504667321e0186ecb1e385183889d89b"
|
sha256: f526d1fbe68875f6119ffc333f114dfe6aa93ad04439276d53968f7977cc410e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0+10"
|
version: "1.0.0+11"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -369,14 +369,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.9"
|
version: "2.3.9"
|
||||||
easy_debounce:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: easy_debounce
|
|
||||||
sha256: f082609cfb8f37defb9e37fc28bc978c6712dedf08d4c5a26f820fa10165a236
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.3"
|
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -769,7 +761,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.2"
|
||||||
image:
|
image:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
|
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
|
||||||
@@ -1701,14 +1693,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.0"
|
version: "0.7.0"
|
||||||
textfield_tags:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: textfield_tags
|
|
||||||
sha256: d1f2204114157a1296bb97c20d7f8c8c7fd036212812afb2e19de7bb34acc55b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.1"
|
|
||||||
timeago:
|
timeago:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
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.0+7
|
version: 1.2.0+9
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.4 <4.0.0"
|
sdk: ">=3.3.4 <4.0.0"
|
||||||
@@ -27,7 +27,6 @@ dependencies:
|
|||||||
crypto: ^3.0.3
|
crypto: ^3.0.3
|
||||||
path: ^1.9.0
|
path: ^1.9.0
|
||||||
intl: ^0.19.0
|
intl: ^0.19.0
|
||||||
image: ^4.1.7
|
|
||||||
font_awesome_flutter: ^10.7.0
|
font_awesome_flutter: ^10.7.0
|
||||||
web_socket_channel: ^3.0.0
|
web_socket_channel: ^3.0.0
|
||||||
permission_handler: ^11.3.1
|
permission_handler: ^11.3.1
|
||||||
@@ -50,7 +49,6 @@ dependencies:
|
|||||||
media_kit: ^1.1.10+1
|
media_kit: ^1.1.10+1
|
||||||
media_kit_video: ^1.2.4
|
media_kit_video: ^1.2.4
|
||||||
media_kit_libs_video: ^1.0.4
|
media_kit_libs_video: ^1.0.4
|
||||||
textfield_tags: ^3.0.1
|
|
||||||
pasteboard: ^0.2.0
|
pasteboard: ^0.2.0
|
||||||
desktop_drop: ^0.4.4
|
desktop_drop: ^0.4.4
|
||||||
badges: ^3.1.2
|
badges: ^3.1.2
|
||||||
@@ -60,7 +58,6 @@ dependencies:
|
|||||||
flutter_cache_manager: ^3.3.3
|
flutter_cache_manager: ^3.3.3
|
||||||
flutter_markdown_selectionarea: ^0.6.17+1
|
flutter_markdown_selectionarea: ^0.6.17+1
|
||||||
shared_preferences: ^2.2.3
|
shared_preferences: ^2.2.3
|
||||||
easy_debounce: ^2.0.3
|
|
||||||
provider: ^6.1.2
|
provider: ^6.1.2
|
||||||
gal: ^2.3.0
|
gal: ^2.3.0
|
||||||
dio: ^5.5.0+1
|
dio: ^5.5.0+1
|
||||||
|
|||||||
Reference in New Issue
Block a user