Show user level

This commit is contained in:
LittleSheep 2024-12-22 19:11:53 +08:00
parent 594f57e0d3
commit 67a29b4305
3 changed files with 79 additions and 8 deletions

View File

@ -0,0 +1,41 @@
import 'package:intl/intl.dart';
const List<int> kExperienceToLevelRequirements = [
0, // Level 0
1000, // Level 1
4000, // Level 2
9000, // Level 3
16000, // Level 4
25000, // Level 5
36000, // Level 6
49000, // Level 7
64000, // Level 8
81000, // Level 9
100000, // Level 10
121000, // Level 11
144000, // Level 12
368000 // Level 13
];
int getLevelFromExp(int experience) {
final exp = kExperienceToLevelRequirements.reversed.firstWhere((x) => x <= experience);
final idx = kExperienceToLevelRequirements.indexOf(exp);
return idx;
}
double calcLevelUpProgress(int experience) {
final exp = kExperienceToLevelRequirements.reversed.firstWhere((x) => x <= experience);
final idx = kExperienceToLevelRequirements.indexOf(exp);
if (idx + 1 >= kExperienceToLevelRequirements.length) return 1;
final nextExp = kExperienceToLevelRequirements[idx + 1];
return (experience - exp).abs() / (exp - nextExp).abs();
}
String calcLevelUpProgressLevel(int experience) {
final exp = kExperienceToLevelRequirements.reversed.firstWhere((x) => x <= experience);
final idx = kExperienceToLevelRequirements.indexOf(exp);
if (idx + 1 >= kExperienceToLevelRequirements.length) return 'Infinity';
final nextExp = exp - kExperienceToLevelRequirements[idx + 1];
final formatter = NumberFormat.compactCurrency(symbol: '', decimalDigits: 1);
return '${formatter.format((exp - experience).abs())}/${formatter.format(nextExp.abs())}';
}

View File

@ -9,6 +9,7 @@ import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:relative_time/relative_time.dart'; import 'package:relative_time/relative_time.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/experience.dart';
import 'package:surface/providers/relationship.dart'; import 'package:surface/providers/relationship.dart';
import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
import 'package:surface/screens/abuse_report.dart'; import 'package:surface/screens/abuse_report.dart';
@ -437,6 +438,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
Column( Column(
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Icon(Symbols.calendar_add_on), const Icon(Symbols.calendar_add_on),
const Gap(8), const Gap(8),
@ -444,6 +446,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
], ],
), ),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Icon(Symbols.cake), const Icon(Symbols.cake),
const Gap(8), const Gap(8),
@ -457,6 +460,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
], ],
), ),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Icon(Symbols.identity_platform), const Icon(Symbols.identity_platform),
const Gap(8), const Gap(8),
@ -466,6 +470,26 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
).opacity(0.8), ).opacity(0.8),
], ],
), ),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Icon(Symbols.star),
const Gap(8),
Text('Lv${getLevelFromExp(_account?.profile?.experience ?? 0)}'),
const Gap(8),
Text(calcLevelUpProgressLevel(_account?.profile?.experience ?? 0)).fontSize(11).opacity(0.5),
const Gap(8),
Container(
width: double.infinity,
constraints: const BoxConstraints(maxWidth: 160),
child: LinearProgressIndicator(
value: calcLevelUpProgress(_account?.profile?.experience ?? 0),
borderRadius: BorderRadius.circular(8),
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
).alignment(Alignment.centerLeft),
),
],
),
], ],
).padding(horizontal: 8), ).padding(horizontal: 8),
], ],

View File

@ -45,17 +45,9 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTi
Future<void> _fetchPublisher() async { Future<void> _fetchPublisher() async {
try { try {
final sn = context.read<SnNetworkProvider>(); final sn = context.read<SnNetworkProvider>();
final ud = context.read<UserDirectoryProvider>();
final rel = context.read<SnRelationshipProvider>();
final resp = await sn.client.get('/cgi/co/publishers/${widget.name}'); final resp = await sn.client.get('/cgi/co/publishers/${widget.name}');
if (!mounted) return; if (!mounted) return;
_publisher = SnPublisher.fromJson(resp.data); _publisher = SnPublisher.fromJson(resp.data);
_account = await ud.getAccount(_publisher?.accountId);
_accountRelationship = await rel.getRelationship(_account!.id);
if (_publisher?.realmId != null && _publisher!.realmId != 0) {
final resp = await sn.client.get('/cgi/id/realms/${_publisher!.realmId}');
_realm = SnRealm.fromJson(resp.data);
}
} catch (err) { } catch (err) {
if (!mounted) return; if (!mounted) return;
context.showErrorDialog(err).then((_) { context.showErrorDialog(err).then((_) {
@ -65,6 +57,20 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTi
} finally { } finally {
setState(() {}); setState(() {});
} }
try {
final sn = context.read<SnNetworkProvider>();
final ud = context.read<UserDirectoryProvider>();
final rel = context.read<SnRelationshipProvider>();
_account = await ud.getAccount(_publisher?.accountId);
_accountRelationship = await rel.getRelationship(_account!.id);
if (_publisher?.realmId != null && _publisher!.realmId != 0) {
final resp = await sn.client.get('/cgi/id/realms/${_publisher!.realmId}');
_realm = SnRealm.fromJson(resp.data);
}
} catch (_) {
// ignore
}
} }
bool _isSubscribing = false; bool _isSubscribing = false;