✨ Show user level
This commit is contained in:
parent
594f57e0d3
commit
67a29b4305
41
lib/providers/experience.dart
Normal file
41
lib/providers/experience.dart
Normal 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())}';
|
||||
}
|
@ -9,6 +9,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:relative_time/relative_time.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/experience.dart';
|
||||
import 'package:surface/providers/relationship.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/screens/abuse_report.dart';
|
||||
@ -437,6 +438,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
||||
Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Symbols.calendar_add_on),
|
||||
const Gap(8),
|
||||
@ -444,6 +446,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Symbols.cake),
|
||||
const Gap(8),
|
||||
@ -457,6 +460,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Symbols.identity_platform),
|
||||
const Gap(8),
|
||||
@ -466,6 +470,26 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
||||
).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),
|
||||
],
|
||||
|
@ -45,17 +45,9 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTi
|
||||
Future<void> _fetchPublisher() async {
|
||||
try {
|
||||
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}');
|
||||
if (!mounted) return;
|
||||
_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) {
|
||||
if (!mounted) return;
|
||||
context.showErrorDialog(err).then((_) {
|
||||
@ -65,6 +57,20 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTi
|
||||
} finally {
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user