Compare commits

..

7 Commits

Author SHA1 Message Date
989b5babd9 Auto update checking 2024-08-03 01:14:42 +08:00
9ea364640d 🚀 Launch 1.2.0+8 2024-08-02 23:24:36 +08:00
a9f55a489d ⬆️ Clean and upgrade packages 2024-08-02 23:22:50 +08:00
4616f3a3e2 Friend request indicator 2024-08-02 23:15:28 +08:00
425bae9d13 💄 Better friend page loading indicator 2024-08-02 22:54:56 +08:00
07771e8979 Improve the speed of fetching attachments meta via batch api 2024-08-02 22:46:48 +08:00
0ad4854443 💄 Grid view in call 2024-08-02 21:12:37 +08:00
17 changed files with 373 additions and 242 deletions

View File

@@ -113,7 +113,7 @@ PODS:
- TOCropViewController (~> 2.7.4)
- image_picker_ios (0.0.1):
- Flutter
- livekit_client (2.2.2):
- livekit_client (2.2.3):
- Flutter
- WebRTC-SDK (= 125.6422.04)
- media_kit_libs_ios_video (1.0.4):
@@ -295,7 +295,7 @@ SPEC CHECKSUMS:
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
livekit_client: c767049a635d5b6d43de3273dca3c439b8a6e970
livekit_client: bad83a7776a41abc42e1f26d903eeac9164c8a9f
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e

View File

@@ -1,8 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart';
import 'package:solian/exts.dart';
import 'package:solian/platform.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/providers/content/channel.dart';
import 'package:solian/providers/content/realm.dart';
@@ -24,6 +26,7 @@ class BootstrapperShell extends StatefulWidget {
class _BootstrapperShellState extends State<BootstrapperShell> {
bool _isBusy = true;
bool _isErrored = false;
bool _isDismissable = true;
String? _subtitle;
Color get _unFocusColor =>
@@ -38,6 +41,32 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
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',
action: () async {
@@ -47,12 +76,14 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
setState(() {
_isErrored = true;
_subtitle = 'bsCheckingServerDown'.tr;
_isDismissable = false;
});
throw Exception('unable connect to server');
} else if (resp.statusCode == null) {
setState(() {
_isErrored = true;
_subtitle = 'bsCheckingServerFail'.tr;
_isDismissable = false;
});
throw Exception('unable connect to server');
}
@@ -85,7 +116,7 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
await Future.wait([
Get.find<RealmProvider>().refreshAvailableRealms(),
Get.find<ChannelProvider>().refreshAvailableChannel(),
Get.find<RelationshipProvider>().refreshFriendList(),
Get.find<RelationshipProvider>().refreshRelativeList(),
]);
}
},
@@ -148,9 +179,11 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
GestureDetector(
child: Column(
children: [
if (_isErrored)
const Icon(Icons.cancel, size: 24)
else
if (_isErrored && !_isDismissable)
const Icon(Icons.cancel, size: 24),
if (_isErrored && _isDismissable)
const Icon(Icons.warning, size: 24),
if (!_isErrored && _isBusy)
const SizedBox(
width: 24,
height: 24,
@@ -161,15 +194,24 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
maxWidth: 280,
child: Column(
children: [
Text(
_subtitle ??
'${_periods[_periodCursor].label.tr} (${_periodCursor + 1}/${_periods.length})',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: _unFocusColor,
if (_subtitle == null)
Text(
'${_periods[_periodCursor].label.tr} (${_periodCursor + 1}/${_periods.length})',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: _unFocusColor,
),
),
),
if (_subtitle != null)
Text(
_subtitle!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: _unFocusColor,
),
).paddingOnly(bottom: 4),
Text(
'2024 © Solsynth LLC',
textAlign: TextAlign.center,
@@ -185,12 +227,19 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
),
onTap: () {
if (_isBusy) return;
setState(() {
_isBusy = true;
_isErrored = false;
_periodCursor = 0;
});
_runPeriods();
if (_isDismissable) {
setState(() {
_isBusy = false;
_isErrored = false;
});
} else {
setState(() {
_isBusy = true;
_isErrored = false;
_periodCursor = 0;
});
_runPeriods();
}
},
)
],

View File

@@ -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) {
var stack = StackTrace.current;
var stackTrace = '$stack';

View File

@@ -2,7 +2,6 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/get_rx/get_rx.dart';
import 'package:livekit_client/livekit_client.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:solian/models/call.dart';

View File

@@ -4,6 +4,7 @@ import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:path/path.dart';
import 'package:solian/models/attachment.dart';
import 'package:solian/models/pagination.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart';
import 'package:dio/dio.dart' as dio;
@@ -21,6 +22,48 @@ class AttachmentProvider extends GetConnect {
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 {
if (!noCache && _cachedResponses.containsKey(id)) {
return _cachedResponses[id]!;

View File

@@ -4,15 +4,19 @@ import 'package:solian/models/relations.dart';
import 'package:solian/providers/auth.dart';
class RelationshipProvider extends GetxController {
final RxInt friendRequestCount = 0.obs;
final RxList<Relationship> _friends = RxList.empty(growable: true);
Future<void> refreshFriendList() async {
final resp = await listRelationWithStatus(1);
_friends.value = resp.body
Future<void> refreshRelativeList() async {
final resp = await listRelation();
final List<Relationship> result = resp.body
.map((e) => Relationship.fromJson(e))
.toList()
.cast<Relationship>();
_friends.value = result.where((x) => x.status == 1).toList();
_friends.refresh();
friendRequestCount.value = result.where((x) => x.status == 0).length;
}
bool hasFriend(Account account) {

View File

@@ -3,11 +3,13 @@ import 'package:get/get.dart';
import 'package:solian/models/account.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/providers/account_status.dart';
import 'package:solian/providers/relation.dart';
import 'package:solian/router.dart';
import 'package:solian/screens/auth/signin.dart';
import 'package:solian/screens/auth/signup.dart';
import 'package:solian/widgets/account/account_heading.dart';
import 'package:solian/widgets/sized_container.dart';
import 'package:badges/badges.dart' as badges;
class AccountScreen extends StatefulWidget {
const AccountScreen({super.key});
@@ -23,9 +25,27 @@ class _AccountScreenState extends State<AccountScreen> {
(
const Icon(Icons.color_lens),
'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();

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart';
import 'package:solian/exts.dart';
import 'package:solian/models/relations.dart';
import 'package:solian/providers/relation.dart';
import 'package:solian/theme.dart';
import 'package:solian/widgets/account/relative_list.dart';
class FriendScreen extends StatefulWidget {
@@ -21,15 +21,15 @@ class _FriendScreenState extends State<FriendScreen>
List<Relationship> _relations = List.empty();
List<Relationship> filterByStatus(int status) {
List<Relationship> _filterByStatus(int status) {
return _relations.where((x) => x.status == status).toList();
}
Future<void> loadRelations() async {
Future<void> _loadRelations() async {
setState(() => _isBusy = true);
final RelationshipProvider provider = Get.find();
final resp = await provider.listRelation();
final RelationshipProvider relations = Get.find();
final resp = await relations.listRelation();
setState(() {
_relations = resp.body
@@ -38,6 +38,9 @@ class _FriendScreenState extends State<FriendScreen>
.cast<Relationship>();
_isBusy = false;
});
relations.friendRequestCount.value =
_relations.where((x) => x.status == 0).length;
}
void promptAddFriend() async {
@@ -104,8 +107,8 @@ class _FriendScreenState extends State<FriendScreen>
super.initState();
_tabController = TabController(length: 3, vsync: this);
loadRelations().then((_) {
if (filterByStatus(0).isEmpty) {
_loadRelations().then((_) {
if (_filterByStatus(0).isEmpty) {
_tabController.animateTo(1);
}
});
@@ -119,6 +122,19 @@ class _FriendScreenState extends State<FriendScreen>
appBar: AppBar(
centerTitle: false,
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(
controller: _tabController,
tabs: const [
@@ -136,46 +152,34 @@ class _FriendScreenState extends State<FriendScreen>
controller: _tabController,
children: [
RefreshIndicator(
onRefresh: () => loadRelations(),
onRefresh: () => _loadRelations(),
child: CustomScrollView(
slivers: [
if (_isBusy)
SliverToBoxAdapter(
child: const LinearProgressIndicator().animate().scaleX(),
),
SilverRelativeList(
items: filterByStatus(0),
onUpdate: () => loadRelations(),
items: _filterByStatus(0),
onUpdate: () => _loadRelations(),
),
],
),
),
RefreshIndicator(
onRefresh: () => loadRelations(),
onRefresh: () => _loadRelations(),
child: CustomScrollView(
slivers: [
if (_isBusy)
SliverToBoxAdapter(
child: const LinearProgressIndicator().animate().scaleX(),
),
SilverRelativeList(
items: filterByStatus(1),
onUpdate: () => loadRelations(),
items: _filterByStatus(1),
onUpdate: () => _loadRelations(),
),
],
),
),
RefreshIndicator(
onRefresh: () => loadRelations(),
onRefresh: () => _loadRelations(),
child: CustomScrollView(
slivers: [
if (_isBusy)
SliverToBoxAdapter(
child: const LinearProgressIndicator().animate().scaleX(),
),
SilverRelativeList(
items: filterByStatus(3),
onUpdate: () => loadRelations(),
items: _filterByStatus(3),
onUpdate: () => _loadRelations(),
),
],
),

View File

@@ -87,75 +87,77 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
Widget _buildListLayout() {
final ChatCallProvider call = Get.find();
return Stack(
children: [
Container(
color: Theme.of(context).colorScheme.surfaceContainer,
child: call.focusTrack.value != null
? InteractiveParticipantWidget(
isFixed: false,
participant: call.focusTrack.value!,
onTap: () {},
)
: const SizedBox(),
),
Positioned(
left: 0,
right: 0,
top: 0,
child: SizedBox(
height: 128,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: math.max(0, call.participantTracks.length),
itemBuilder: (BuildContext context, int index) {
final track = call.participantTracks[index];
if (track.participant.sid ==
call.focusTrack.value?.participant.sid) {
return Container();
}
return Obx(
() => Stack(
children: [
Container(
color: Theme.of(context).colorScheme.surfaceContainer,
child: call.focusTrack.value != null
? InteractiveParticipantWidget(
isFixedAvatar: false,
participant: call.focusTrack.value!,
onTap: () {},
)
: const SizedBox(),
),
Positioned(
left: 0,
right: 0,
top: 0,
child: SizedBox(
height: 128,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: math.max(0, call.participantTracks.length),
itemBuilder: (BuildContext context, int index) {
final track = call.participantTracks[index];
if (track.participant.sid ==
call.focusTrack.value?.participant.sid) {
return Container();
}
return Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget(
isFixed: true,
width: 120,
height: 120,
color: Theme.of(context).cardColor,
participant: track,
onTap: () {
if (track.participant.sid !=
call.focusTrack.value?.participant.sid) {
call.changeFocusTrack(track);
}
},
return Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget(
isFixedAvatar: true,
width: 120,
height: 120,
color: Theme.of(context).cardColor,
participant: track,
onTap: () {
if (track.participant.sid !=
call.focusTrack.value?.participant.sid) {
call.changeFocusTrack(track);
}
},
),
),
),
);
},
);
},
),
),
),
),
],
],
),
);
}
Widget _buildGridLayout() {
final ChatCallProvider call = Get.find();
return LayoutBuilder(
builder: (context, constraints) {
double screenWidth = constraints.maxWidth;
double screenHeight = constraints.maxHeight;
return LayoutBuilder(builder: (context, constraints) {
double screenWidth = constraints.maxWidth;
double screenHeight = constraints.maxHeight;
int columns = (math.sqrt(call.participantTracks.length)).ceil();
int rows = (call.participantTracks.length / columns).ceil();
int columns = (math.sqrt(call.participantTracks.length)).ceil();
int rows = (call.participantTracks.length / columns).ceil();
double tileWidth = screenWidth / columns;
double tileHeight = screenHeight / rows;
double tileWidth = screenWidth / columns;
double tileHeight = screenHeight / rows;
return GridView.builder(
return Obx(
() => GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: columns,
childAspectRatio: tileWidth / tileHeight,
@@ -165,25 +167,26 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
final track = call.participantTracks[index];
return Padding(
padding: const EdgeInsets.all(16),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget(
isFixed: true,
color: Theme.of(context).colorScheme.surfaceContainerLow,
participant: track,
onTap: () {
if (track.participant.sid !=
call.focusTrack.value?.participant.sid) {
call.changeFocusTrack(track);
}
},
child: Card(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget(
color: Theme.of(context).colorScheme.surfaceContainerHigh,
participant: track,
onTap: () {
if (track.participant.sid !=
call.focusTrack.value?.participant.sid) {
call.changeFocusTrack(track);
}
},
),
),
),
);
},
);
}
);
),
);
});
}
@override
@@ -234,31 +237,33 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
body: SafeArea(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Obx(
() => Column(
children: [
SizeTransition(
sizeFactor: _controlsAnimation,
axis: Axis.vertical,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: 64,
child: Row(
children: [
const Expanded(child: SizedBox()),
IconButton(
icon: _layoutMode == 0
? const Icon(Icons.view_list)
: const Icon(Icons.grid_view),
onPressed: () {
_switchLayout();
},
),
],
).paddingSymmetric(horizontal: 10),
),
child: Column(
children: [
SizeTransition(
sizeFactor: _controlsAnimation,
axis: Axis.vertical,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: 64,
child: Row(
children: [
const Expanded(child: SizedBox()),
IconButton(
icon: _layoutMode == 0
? const Icon(Icons.view_list)
: const Icon(Icons.grid_view),
onPressed: () {
_switchLayout();
},
),
],
).paddingSymmetric(horizontal: 10),
),
Expanded(
),
Expanded(
child: Material(
color: Theme.of(context).colorScheme.surfaceContainerLow,
elevation: 2,
child: Builder(
builder: (context) {
switch (_layoutMode) {
@@ -270,20 +275,20 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
},
),
),
if (provider.room.localParticipant != null)
SizeTransition(
sizeFactor: _controlsAnimation,
axis: Axis.vertical,
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: ControlsWidget(
provider.room,
provider.room.localParticipant!,
),
),
if (provider.room.localParticipant != null)
SizeTransition(
sizeFactor: _controlsAnimation,
axis: Axis.vertical,
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: ControlsWidget(
provider.room,
provider.room.localParticipant!,
),
),
],
),
),
],
),
onTap: () {
_toggleControls();

View File

@@ -314,6 +314,11 @@ const i18nEnglish = {
'accountStatusNeutral': 'Neutral',
'accountStatusPositive': 'Positive',
'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',
'bsCheckingServerFail':
'Unable connect to server, check your network connection',

View File

@@ -293,6 +293,11 @@ const i18nSimplifiedChinese = {
'accountStatusNeutral': '中性',
'accountStatusPositive': '积极',
'bsLoadingTheme': '正在装载主题',
'bsCheckForUpdate': '正在检查更新',
'bsCheckForUpdateFailed': '无法检查更新',
'bsCheckForUpdateNew': '发现新版本',
'bsCheckForUpdateDescApple': '请前往 TestFlight 并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。',
'bsCheckForUpdateDescCommon': '请前往我们的网站下载并安装最新版本的应用程序,以防止出现错误并获取最新功能。',
'bsCheckingServer': '检查服务器状态中',
'bsCheckingServerFail': '无法连接至服务器,请检查你的网络连接状态',
'bsCheckingServerDown': '当前服务器不可用,请稍后重试',

View File

@@ -222,19 +222,13 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
setState(() => _isBusy = true);
int progress = 0;
for (var idx = 0; idx < widget.initialAttachments.length; idx++) {
attach.getMetadata(widget.initialAttachments[idx]).then((resp) {
progress++;
_attachments[idx] = resp;
if (progress == widget.initialAttachments.length) {
setState(() {
_isBusy = false;
_isFirstTimeBusy = false;
});
}
attach.listMetadata(widget.initialAttachments).then((result) {
setState(() {
_attachments = result;
_isBusy = false;
_isFirstTimeBusy = false;
});
}
});
}
void _showAttachmentPreview(Attachment element) {

View File

@@ -45,7 +45,7 @@ class _AttachmentListState extends State<AttachmentList> {
List<Attachment?> _attachmentsMeta = List.empty();
void _getMetadataList() {
final AttachmentProvider provider = Get.find();
final AttachmentProvider attach = Get.find();
if (widget.attachmentsId.isEmpty) {
return;
@@ -53,25 +53,16 @@ class _AttachmentListState extends State<AttachmentList> {
_attachmentsMeta = List.filled(widget.attachmentsId.length, null);
}
int progress = 0;
for (var idx = 0; idx < widget.attachmentsId.length; idx++) {
provider.getMetadata(widget.attachmentsId[idx]).then((resp) {
progress++;
if (resp != null) {
_attachmentsMeta[idx] = resp;
}
if (progress == widget.attachmentsId.length) {
calculateAspectRatio();
if (mounted) {
setState(() => _isLoading = false);
}
}
attach.listMetadata(widget.attachmentsId).then((result) {
setState(() {
_attachmentsMeta = result;
_isLoading = false;
});
}
_calculateAspectRatio();
});
}
void calculateAspectRatio() {
void _calculateAspectRatio() {
bool isConsistent = true;
double? consistentValue;
int portrait = 0, square = 0, landscape = 0;

View File

@@ -201,7 +201,7 @@ class InteractiveParticipantWidget extends StatelessWidget {
final double? width;
final double? height;
final Color? color;
final bool isFixed;
final bool isFixedAvatar;
final ParticipantTrack participant;
final Function() onTap;
@@ -210,7 +210,7 @@ class InteractiveParticipantWidget extends StatelessWidget {
this.width,
this.height,
this.color,
this.isFixed = false,
this.isFixedAvatar = false,
required this.participant,
required this.onTap,
});
@@ -222,7 +222,7 @@ class InteractiveParticipantWidget extends StatelessWidget {
width: width,
height: height,
color: color,
child: ParticipantWidget.widgetFor(participant, isFixed: isFixed),
child: ParticipantWidget.widgetFor(participant, isFixed: isFixedAvatar),
),
onTap: () => onTap(),
onLongPress: () {

View File

@@ -4,6 +4,7 @@ import 'package:solian/models/account_status.dart';
import 'package:solian/providers/account_status.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/providers/content/channel.dart';
import 'package:solian/providers/relation.dart';
import 'package:solian/router.dart';
import 'package:solian/shells/root_shell.dart';
import 'package:solian/theme.dart';
@@ -60,8 +61,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
AppRouter.instance.pushNamed('settings');
setState(() => _selectedIndex = null);
_closeDrawer();
}
);
});
}
@override
@@ -130,22 +130,36 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
);
},
),
leading: Builder(builder: (context) {
final badgeColor = _accountStatus != null
leading: Obx(() {
final statusBadgeColor = _accountStatus != null
? StatusProvider.determineStatus(
_accountStatus!,
).$2
: Colors.grey;
final RelationshipProvider relations = Get.find();
final accountNotifications = relations.friendRequestCount.value;
return badges.Badge(
showBadge: _accountStatus != null,
badgeStyle: badges.BadgeStyle(badgeColor: badgeColor),
position: badges.BadgePosition.bottomEnd(
bottom: 0,
end: -2,
badgeContent: Text(
accountNotifications.toString(),
style: const TextStyle(color: Colors.white),
),
child: AccountAvatar(
content: auth.userProfile.value!['avatar'],
showBadge: accountNotifications > 0,
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'],
),
),
);
}),

View File

@@ -261,10 +261,10 @@ packages:
dependency: transitive
description:
name: cross_file
sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
url: "https://pub.dev"
source: hosted
version: "0.3.4+1"
version: "0.3.4+2"
crypto:
dependency: "direct main"
description:
@@ -317,10 +317,10 @@ packages:
dependency: transitive
description:
name: dev_build
sha256: "76dd5b2587a891ab9c1e7f7eea6ca4a3504667321e0186ecb1e385183889d89b"
sha256: f526d1fbe68875f6119ffc333f114dfe6aa93ad04439276d53968f7977cc410e
url: "https://pub.dev"
source: hosted
version: "1.0.0+10"
version: "1.0.0+11"
device_info_plus:
dependency: "direct main"
description:
@@ -369,14 +369,6 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:
@@ -684,10 +676,10 @@ packages:
dependency: "direct main"
description:
name: flutter_webrtc
sha256: d305793e6737c59a81c45b18484e1f985710827704eeb9092573387efcbae272
sha256: f46bd76cef6e8d787dc707d0c591f0e89c912a2970c7b5e68a55b9cca1bdde4c
url: "https://pub.dev"
source: hosted
version: "0.11.5"
version: "0.11.6"
font_awesome_flutter:
dependency: "direct main"
description:
@@ -732,10 +724,10 @@ packages:
dependency: "direct main"
description:
name: go_router
sha256: "39dd52168d6c59984454183148dc3a5776960c61083adfc708cc79a7b3ce1ba8"
sha256: d380de0355788c5c784fe9f81b43fc833b903991c25ecc4e2a416a67faefa722
url: "https://pub.dev"
source: hosted
version: "14.2.1"
version: "14.2.2"
graphs:
dependency: transitive
description:
@@ -769,7 +761,7 @@ packages:
source: hosted
version: "4.0.2"
image:
dependency: "direct main"
dependency: transitive
description:
name: image
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
@@ -820,10 +812,10 @@ packages:
dependency: transitive
description:
name: image_picker_for_web
sha256: "5d6eb13048cd47b60dbf1a5495424dea226c5faf3950e20bf8120a58efb5b5f3"
sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50"
url: "https://pub.dev"
source: hosted
version: "3.0.4"
version: "3.0.5"
image_picker_ios:
dependency: transitive
description:
@@ -948,10 +940,10 @@ packages:
dependency: "direct main"
description:
name: livekit_client
sha256: e6b1e8a3cdcae95f7e62c0371590648444bac245fce3a1bcfb4ec05889ad82f3
sha256: be2a3375851a6147d5de94a870edd6e831ab8d3d793e3563ba1ff1b05490b3de
url: "https://pub.dev"
source: hosted
version: "2.2.2"
version: "2.2.3"
logging:
dependency: transitive
description:
@@ -1524,10 +1516,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_web
sha256: "3a293170d4d9403c3254ee05b84e62e8a9b3c5808ebd17de6a33fe9ea6457936"
sha256: "59dc807b94d29d52ddbb1b3c0d3b9d0a67fc535a64e62a5542c8db0513fcb6c2"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
version: "2.4.1"
shared_preferences_windows:
dependency: transitive
description:
@@ -1701,14 +1693,6 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: "direct main"
description:
@@ -1809,10 +1793,10 @@ packages:
dependency: transitive
description:
name: url_launcher_web
sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
sha256: a36e2d7981122fa185006b216eb6b5b97ede3f9a54b7a511bc966971ab98d049
url: "https://pub.dev"
source: hosted
version: "2.3.1"
version: "2.3.2"
url_launcher_windows:
dependency: transitive
description:

View File

@@ -2,7 +2,7 @@ name: solian
description: "The Solar Network App"
publish_to: "none"
version: 1.2.0+7
version: 1.2.0+9
environment:
sdk: ">=3.3.4 <4.0.0"
@@ -27,7 +27,6 @@ dependencies:
crypto: ^3.0.3
path: ^1.9.0
intl: ^0.19.0
image: ^4.1.7
font_awesome_flutter: ^10.7.0
web_socket_channel: ^3.0.0
permission_handler: ^11.3.1
@@ -50,7 +49,6 @@ dependencies:
media_kit: ^1.1.10+1
media_kit_video: ^1.2.4
media_kit_libs_video: ^1.0.4
textfield_tags: ^3.0.1
pasteboard: ^0.2.0
desktop_drop: ^0.4.4
badges: ^3.1.2
@@ -60,7 +58,6 @@ dependencies:
flutter_cache_manager: ^3.3.3
flutter_markdown_selectionarea: ^0.6.17+1
shared_preferences: ^2.2.3
easy_debounce: ^2.0.3
provider: ^6.1.2
gal: ^2.3.0
dio: ^5.5.0+1