✨ Enrich user profile settings
This commit is contained in:
parent
be01bac5db
commit
0424eb0c2a
@ -413,5 +413,15 @@
|
||||
"chatBreakSet": "Break set for {}",
|
||||
"chatBreakCleared": "Chat break has been cleared.",
|
||||
"chatBreakCustom": "Custom duration",
|
||||
"chatBreakEnterMinutes": "Enter minutes"
|
||||
"chatBreakEnterMinutes": "Enter minutes",
|
||||
"firstName": "First Name",
|
||||
"middleName": "Middle Name",
|
||||
"lastName": "Last Name",
|
||||
"gender": "Gender",
|
||||
"pronouns": "Pronouns",
|
||||
"location": "Location",
|
||||
"timeZone": "Time Zone",
|
||||
"birthday": "Birthday",
|
||||
"selectADate": "Select a date",
|
||||
"useDeviceTimeZone": "Use device time zone"
|
||||
}
|
||||
|
@ -84,6 +84,8 @@ PODS:
|
||||
- Flutter
|
||||
- flutter_platform_alert (0.0.1):
|
||||
- Flutter
|
||||
- flutter_timezone (0.0.1):
|
||||
- Flutter
|
||||
- flutter_udid (0.0.1):
|
||||
- Flutter
|
||||
- SAMKeychain
|
||||
@ -204,6 +206,7 @@ DEPENDENCIES:
|
||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
||||
- flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`)
|
||||
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
||||
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
|
||||
- gal (from `.symlinks/plugins/gal/darwin`)
|
||||
@ -268,6 +271,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_platform_alert:
|
||||
:path: ".symlinks/plugins/flutter_platform_alert/ios"
|
||||
flutter_timezone:
|
||||
:path: ".symlinks/plugins/flutter_timezone/ios"
|
||||
flutter_udid:
|
||||
:path: ".symlinks/plugins/flutter_udid/ios"
|
||||
flutter_webrtc:
|
||||
@ -326,6 +331,7 @@ SPEC CHECKSUMS:
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||
flutter_webrtc: fd0d3bdef8766a0736dbbe2e5b7e85f1f3c52117
|
||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||
|
@ -19,6 +19,7 @@ import 'package:island/pods/websocket.dart';
|
||||
import 'package:island/route.dart';
|
||||
import 'package:island/screens/auth/tabs.dart';
|
||||
import 'package:island/services/notify.dart';
|
||||
import 'package:island/services/timezone.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:relative_time/relative_time.dart';
|
||||
@ -45,6 +46,14 @@ void main() async {
|
||||
showErrorAlert(err);
|
||||
}
|
||||
|
||||
try {
|
||||
log("[SplashScreen] Loading timezone database...");
|
||||
await initializeTzdb();
|
||||
log("[SplashScreen] Time zone database was loaded!");
|
||||
} catch (err) {
|
||||
log("[SplashScreen] Failed to load timezone database... $err");
|
||||
}
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
if (!kIsWeb && (Platform.isMacOS || Platform.isLinux || Platform.isWindows)) {
|
||||
|
@ -31,6 +31,13 @@ sealed class SnAccountProfile with _$SnAccountProfile {
|
||||
required String? middleName,
|
||||
required String? lastName,
|
||||
@Default('') String bio,
|
||||
@Default('') String gender,
|
||||
@Default('') String pronouns,
|
||||
@Default('') String location,
|
||||
@Default('') String timeZone,
|
||||
DateTime? birthday,
|
||||
DateTime? lastSeenAt,
|
||||
SnAccountBadge? activeBadge,
|
||||
required int experience,
|
||||
required int level,
|
||||
required double levelingProgress,
|
||||
@ -79,6 +86,7 @@ sealed class SnAccountBadge with _$SnAccountBadge {
|
||||
required String accountId,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? activatedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) = _SnAccountBadge;
|
||||
|
||||
|
@ -200,7 +200,7 @@ $SnAccountProfileCopyWith<$Res> get profile {
|
||||
/// @nodoc
|
||||
mixin _$SnAccountProfile {
|
||||
|
||||
String get id; String? get firstName; String? get middleName; String? get lastName; String get bio; int get experience; int get level; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; String? get firstName; String? get middleName; String? get lastName; String get bio; String get gender; String get pronouns; String get location; String get timeZone; DateTime? get birthday; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@ -213,16 +213,16 @@ $SnAccountProfileCopyWith<SnAccountProfile> get copyWith => _$SnAccountProfileCo
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,firstName,middleName,lastName,bio,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,lastSeenAt,activeBadge,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@ -233,11 +233,11 @@ abstract mixin class $SnAccountProfileCopyWith<$Res> {
|
||||
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String? firstName, String? middleName, String? lastName, String bio, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String? firstName, String? middleName, String? lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;
|
||||
$SnAccountBadgeCopyWith<$Res>? get activeBadge;$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@ -250,14 +250,21 @@ class _$SnAccountProfileCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,middleName: freezed == middleName ? _self.middleName : middleName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
||||
as String,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||
as String,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable
|
||||
as String,pronouns: null == pronouns ? _self.pronouns : pronouns // ignore: cast_nullable_to_non_nullable
|
||||
as String,location: null == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||
as String,timeZone: null == timeZone ? _self.timeZone : timeZone // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthday: freezed == birthday ? _self.birthday : birthday // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : lastSeenAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||
@ -273,6 +280,18 @@ as DateTime?,
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountBadgeCopyWith<$Res>? get activeBadge {
|
||||
if (_self.activeBadge == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountBadgeCopyWith<$Res>(_self.activeBadge!, (value) {
|
||||
return _then(_self.copyWith(activeBadge: value));
|
||||
});
|
||||
}/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnCloudFileCopyWith<$Res>? get picture {
|
||||
if (_self.picture == null) {
|
||||
return null;
|
||||
@ -313,7 +332,7 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAccountProfile implements SnAccountProfile {
|
||||
const _SnAccountProfile({required this.id, required this.firstName, required this.middleName, required this.lastName, this.bio = '', required this.experience, required this.level, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||
const _SnAccountProfile({required this.id, required this.firstName, required this.middleName, required this.lastName, this.bio = '', this.gender = '', this.pronouns = '', this.location = '', this.timeZone = '', this.birthday, this.lastSeenAt, this.activeBadge, required this.experience, required this.level, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||
factory _SnAccountProfile.fromJson(Map<String, dynamic> json) => _$SnAccountProfileFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@ -321,6 +340,13 @@ class _SnAccountProfile implements SnAccountProfile {
|
||||
@override final String? middleName;
|
||||
@override final String? lastName;
|
||||
@override@JsonKey() final String bio;
|
||||
@override@JsonKey() final String gender;
|
||||
@override@JsonKey() final String pronouns;
|
||||
@override@JsonKey() final String location;
|
||||
@override@JsonKey() final String timeZone;
|
||||
@override final DateTime? birthday;
|
||||
@override final DateTime? lastSeenAt;
|
||||
@override final SnAccountBadge? activeBadge;
|
||||
@override final int experience;
|
||||
@override final int level;
|
||||
@override final double levelingProgress;
|
||||
@ -344,16 +370,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,firstName,middleName,lastName,bio,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,lastSeenAt,activeBadge,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@ -364,11 +390,11 @@ abstract mixin class _$SnAccountProfileCopyWith<$Res> implements $SnAccountProfi
|
||||
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String? firstName, String? middleName, String? lastName, String bio, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String? firstName, String? middleName, String? lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;
|
||||
@override $SnAccountBadgeCopyWith<$Res>? get activeBadge;@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@ -381,14 +407,21 @@ class __$SnAccountProfileCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnAccountProfile(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,middleName: freezed == middleName ? _self.middleName : middleName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
||||
as String,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||
as String,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable
|
||||
as String,pronouns: null == pronouns ? _self.pronouns : pronouns // ignore: cast_nullable_to_non_nullable
|
||||
as String,location: null == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||
as String,timeZone: null == timeZone ? _self.timeZone : timeZone // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthday: freezed == birthday ? _self.birthday : birthday // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : lastSeenAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||
@ -405,6 +438,18 @@ as DateTime?,
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountBadgeCopyWith<$Res>? get activeBadge {
|
||||
if (_self.activeBadge == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountBadgeCopyWith<$Res>(_self.activeBadge!, (value) {
|
||||
return _then(_self.copyWith(activeBadge: value));
|
||||
});
|
||||
}/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnCloudFileCopyWith<$Res>? get picture {
|
||||
if (_self.picture == null) {
|
||||
return null;
|
||||
@ -610,7 +655,7 @@ as DateTime?,
|
||||
/// @nodoc
|
||||
mixin _$SnAccountBadge {
|
||||
|
||||
String get id; String get type; String? get label; String? get caption; Map<String, dynamic> get meta; DateTime? get expiredAt; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; String get type; String? get label; String? get caption; Map<String, dynamic> get meta; DateTime? get expiredAt; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get activatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnAccountBadge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@ -623,16 +668,16 @@ $SnAccountBadgeCopyWith<SnAccountBadge> get copyWith => _$SnAccountBadgeCopyWith
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountBadge&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.label, label) || other.label == label)&&(identical(other.caption, caption) || other.caption == caption)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountBadge&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.label, label) || other.label == label)&&(identical(other.caption, caption) || other.caption == caption)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.activatedAt, activatedAt) || other.activatedAt == activatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,type,label,caption,const DeepCollectionEquality().hash(meta),expiredAt,accountId,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,type,label,caption,const DeepCollectionEquality().hash(meta),expiredAt,accountId,createdAt,updatedAt,activatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, activatedAt: $activatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@ -643,7 +688,7 @@ abstract mixin class $SnAccountBadgeCopyWith<$Res> {
|
||||
factory $SnAccountBadgeCopyWith(SnAccountBadge value, $Res Function(SnAccountBadge) _then) = _$SnAccountBadgeCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? activatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@ -660,7 +705,7 @@ class _$SnAccountBadgeCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAccountBadge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? label = freezed,Object? caption = freezed,Object? meta = null,Object? expiredAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? label = freezed,Object? caption = freezed,Object? meta = null,Object? expiredAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? activatedAt = freezed,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
@ -671,7 +716,8 @@ as Map<String, dynamic>,expiredAt: freezed == expiredAt ? _self.expiredAt : expi
|
||||
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,activatedAt: freezed == activatedAt ? _self.activatedAt : activatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
@ -683,7 +729,7 @@ as DateTime?,
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAccountBadge implements SnAccountBadge {
|
||||
const _SnAccountBadge({required this.id, required this.type, required this.label, required this.caption, required final Map<String, dynamic> meta, required this.expiredAt, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta;
|
||||
const _SnAccountBadge({required this.id, required this.type, required this.label, required this.caption, required final Map<String, dynamic> meta, required this.expiredAt, required this.accountId, required this.createdAt, required this.updatedAt, required this.activatedAt, required this.deletedAt}): _meta = meta;
|
||||
factory _SnAccountBadge.fromJson(Map<String, dynamic> json) => _$SnAccountBadgeFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@ -701,6 +747,7 @@ class _SnAccountBadge implements SnAccountBadge {
|
||||
@override final String accountId;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? activatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
|
||||
/// Create a copy of SnAccountBadge
|
||||
@ -716,16 +763,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountBadge&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.label, label) || other.label == label)&&(identical(other.caption, caption) || other.caption == caption)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountBadge&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.label, label) || other.label == label)&&(identical(other.caption, caption) || other.caption == caption)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.activatedAt, activatedAt) || other.activatedAt == activatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,type,label,caption,const DeepCollectionEquality().hash(_meta),expiredAt,accountId,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,type,label,caption,const DeepCollectionEquality().hash(_meta),expiredAt,accountId,createdAt,updatedAt,activatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, activatedAt: $activatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@ -736,7 +783,7 @@ abstract mixin class _$SnAccountBadgeCopyWith<$Res> implements $SnAccountBadgeCo
|
||||
factory _$SnAccountBadgeCopyWith(_SnAccountBadge value, $Res Function(_SnAccountBadge) _then) = __$SnAccountBadgeCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? activatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@ -753,7 +800,7 @@ class __$SnAccountBadgeCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAccountBadge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? label = freezed,Object? caption = freezed,Object? meta = null,Object? expiredAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? label = freezed,Object? caption = freezed,Object? meta = null,Object? expiredAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? activatedAt = freezed,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnAccountBadge(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
@ -764,7 +811,8 @@ as Map<String, dynamic>,expiredAt: freezed == expiredAt ? _self.expiredAt : expi
|
||||
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,activatedAt: freezed == activatedAt ? _self.activatedAt : activatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
@ -47,6 +47,24 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
||||
middleName: json['middle_name'] as String?,
|
||||
lastName: json['last_name'] as String?,
|
||||
bio: json['bio'] as String? ?? '',
|
||||
gender: json['gender'] as String? ?? '',
|
||||
pronouns: json['pronouns'] as String? ?? '',
|
||||
location: json['location'] as String? ?? '',
|
||||
timeZone: json['time_zone'] as String? ?? '',
|
||||
birthday:
|
||||
json['birthday'] == null
|
||||
? null
|
||||
: DateTime.parse(json['birthday'] as String),
|
||||
lastSeenAt:
|
||||
json['last_seen_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_seen_at'] as String),
|
||||
activeBadge:
|
||||
json['active_badge'] == null
|
||||
? null
|
||||
: SnAccountBadge.fromJson(
|
||||
json['active_badge'] as Map<String, dynamic>,
|
||||
),
|
||||
experience: (json['experience'] as num).toInt(),
|
||||
level: (json['level'] as num).toInt(),
|
||||
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
||||
@ -81,6 +99,13 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
||||
'middle_name': instance.middleName,
|
||||
'last_name': instance.lastName,
|
||||
'bio': instance.bio,
|
||||
'gender': instance.gender,
|
||||
'pronouns': instance.pronouns,
|
||||
'location': instance.location,
|
||||
'time_zone': instance.timeZone,
|
||||
'birthday': instance.birthday?.toIso8601String(),
|
||||
'last_seen_at': instance.lastSeenAt?.toIso8601String(),
|
||||
'active_badge': instance.activeBadge?.toJson(),
|
||||
'experience': instance.experience,
|
||||
'level': instance.level,
|
||||
'leveling_progress': instance.levelingProgress,
|
||||
@ -144,6 +169,10 @@ _SnAccountBadge _$SnAccountBadgeFromJson(Map<String, dynamic> json) =>
|
||||
accountId: json['account_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
activatedAt:
|
||||
json['activated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['activated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
@ -161,6 +190,7 @@ Map<String, dynamic> _$SnAccountBadgeToJson(_SnAccountBadge instance) =>
|
||||
'account_id': instance.accountId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'activated_at': instance.activatedAt?.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@ import 'package:island/pods/config.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/services/file.dart';
|
||||
import 'package:island/services/timezone.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
@ -120,9 +121,31 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
final formKeyProfile = useMemoized(GlobalKey<FormState>.new, const []);
|
||||
final birthday = useState<DateTime?>(user.value!.profile.birthday);
|
||||
final firstNameController = useTextEditingController(
|
||||
text: user.value!.profile.firstName,
|
||||
);
|
||||
final middleNameController = useTextEditingController(
|
||||
text: user.value!.profile.middleName,
|
||||
);
|
||||
final lastNameController = useTextEditingController(
|
||||
text: user.value!.profile.lastName,
|
||||
);
|
||||
final bioController = useTextEditingController(
|
||||
text: user.value!.profile.bio,
|
||||
);
|
||||
final genderController = useTextEditingController(
|
||||
text: user.value!.profile.gender,
|
||||
);
|
||||
final pronounsController = useTextEditingController(
|
||||
text: user.value!.profile.pronouns,
|
||||
);
|
||||
final locationController = useTextEditingController(
|
||||
text: user.value!.profile.location,
|
||||
);
|
||||
final timeZoneController = useTextEditingController(
|
||||
text: user.value!.profile.timeZone,
|
||||
);
|
||||
|
||||
void updateProfile() async {
|
||||
if (!formKeyProfile.currentState!.validate()) return;
|
||||
@ -132,7 +155,17 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.patch(
|
||||
'/accounts/me/profile',
|
||||
data: {'bio': bioController.text},
|
||||
data: {
|
||||
'bio': bioController.text,
|
||||
'first_name': firstNameController.text,
|
||||
'middle_name': middleNameController.text,
|
||||
'last_name': lastNameController.text,
|
||||
'gender': genderController.text,
|
||||
'pronouns': pronounsController.text,
|
||||
'location': locationController.text,
|
||||
'time_zone': timeZoneController.text,
|
||||
'birthday': birthday.value?.toIso8601String(),
|
||||
},
|
||||
);
|
||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||
userNotifier.fetchUser();
|
||||
@ -268,6 +301,45 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 16,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'firstName'.tr(),
|
||||
),
|
||||
controller: firstNameController,
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'middleName'.tr(),
|
||||
),
|
||||
controller: middleNameController,
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'lastName'.tr(),
|
||||
),
|
||||
controller: lastNameController,
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: 'bio'.tr()),
|
||||
maxLines: null,
|
||||
@ -276,6 +348,213 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
onTapOutside:
|
||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
Row(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Autocomplete<String>(
|
||||
optionsBuilder: (TextEditingValue textEditingValue) {
|
||||
final options = ['Male', 'Female'];
|
||||
if (textEditingValue.text == '') {
|
||||
return options;
|
||||
}
|
||||
return options.where(
|
||||
(option) => option.toLowerCase().contains(
|
||||
textEditingValue.text.toLowerCase(),
|
||||
),
|
||||
);
|
||||
},
|
||||
onSelected: (String selection) {
|
||||
genderController.text = selection;
|
||||
},
|
||||
fieldViewBuilder: (
|
||||
context,
|
||||
controller,
|
||||
focusNode,
|
||||
onFieldSubmitted,
|
||||
) {
|
||||
// Initialize the controller with the current value
|
||||
if (controller.text.isEmpty &&
|
||||
genderController.text.isNotEmpty) {
|
||||
controller.text = genderController.text;
|
||||
}
|
||||
|
||||
return TextFormField(
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'gender'.tr(),
|
||||
),
|
||||
onChanged: (value) {
|
||||
genderController.text = value;
|
||||
},
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus
|
||||
?.unfocus(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'pronouns'.tr(),
|
||||
),
|
||||
controller: pronounsController,
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'location'.tr(),
|
||||
),
|
||||
controller: locationController,
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Autocomplete<String>(
|
||||
optionsBuilder: (TextEditingValue textEditingValue) {
|
||||
if (textEditingValue.text.isEmpty) {
|
||||
return const Iterable<String>.empty();
|
||||
}
|
||||
final lowercaseQuery =
|
||||
textEditingValue.text.toLowerCase();
|
||||
return getAvailableTz().where((tz) {
|
||||
return tz.toLowerCase().contains(lowercaseQuery);
|
||||
});
|
||||
},
|
||||
onSelected: (String selection) {
|
||||
timeZoneController.text = selection;
|
||||
},
|
||||
fieldViewBuilder: (
|
||||
context,
|
||||
controller,
|
||||
focusNode,
|
||||
onFieldSubmitted,
|
||||
) {
|
||||
// Sync the controller with timeZoneController when the widget is built
|
||||
if (controller.text != timeZoneController.text) {
|
||||
controller.text = timeZoneController.text;
|
||||
}
|
||||
|
||||
return TextFormField(
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'timeZone'.tr(),
|
||||
suffix: InkWell(
|
||||
child: const Icon(
|
||||
Symbols.my_location,
|
||||
size: 18,
|
||||
),
|
||||
onTap: () async {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final machineTz = await getMachineTz();
|
||||
controller.text = machineTz;
|
||||
timeZoneController.text = machineTz;
|
||||
} finally {
|
||||
if (context.mounted) {
|
||||
hideLoadingModal(context);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
onChanged: (value) {
|
||||
timeZoneController.text = value;
|
||||
},
|
||||
);
|
||||
},
|
||||
optionsViewBuilder: (context, onSelected, options) {
|
||||
return Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Material(
|
||||
elevation: 4.0,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: 200,
|
||||
maxWidth: 300,
|
||||
),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
itemCount: options.length,
|
||||
itemBuilder: (
|
||||
BuildContext context,
|
||||
int index,
|
||||
) {
|
||||
final option = options.elementAt(index);
|
||||
return ListTile(
|
||||
title: Text(
|
||||
option,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onTap: () {
|
||||
onSelected(option);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
final date = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: birthday.value ?? DateTime.now(),
|
||||
firstDate: DateTime(1900),
|
||||
lastDate: DateTime.now(),
|
||||
);
|
||||
if (date != null) {
|
||||
birthday.value = date;
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
'birthday'.tr(),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
birthday.value != null
|
||||
? DateFormat.yMMMd().format(birthday.value!)
|
||||
: 'Select a date'.tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton.icon(
|
||||
|
18
lib/services/time.dart
Normal file
18
lib/services/time.dart
Normal file
@ -0,0 +1,18 @@
|
||||
extension DurationFormatter on Duration {
|
||||
String formatDuration() {
|
||||
final isNegative = inMicroseconds < 0;
|
||||
final positiveDuration = isNegative ? -this : this;
|
||||
|
||||
final hours = positiveDuration.inHours.toString().padLeft(2, '0');
|
||||
final minutes = (positiveDuration.inMinutes % 60).toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
final seconds = (positiveDuration.inSeconds % 60).toString().padLeft(
|
||||
2,
|
||||
'0',
|
||||
);
|
||||
|
||||
return '${isNegative ? '-' : ''}$hours:$minutes:$seconds';
|
||||
}
|
||||
}
|
1
lib/services/timezone.dart
Normal file
1
lib/services/timezone.dart
Normal file
@ -0,0 +1 @@
|
||||
export 'timezone/native.dart' if (dart.library.html) 'timezone/web.dart';
|
22
lib/services/timezone/native.dart
Normal file
22
lib/services/timezone/native.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:flutter_timezone/flutter_timezone.dart';
|
||||
import 'package:timezone/standalone.dart' as tz;
|
||||
import 'package:timezone/data/latest_all.dart' as tzdb;
|
||||
|
||||
Future<void> initializeTzdb() async {
|
||||
tzdb.initializeTimeZones();
|
||||
}
|
||||
|
||||
(Duration offset, DateTime now) getTzInfo(String name) {
|
||||
final location = tz.getLocation(name);
|
||||
final now = tz.TZDateTime.now(location);
|
||||
final offset = now.timeZoneOffset;
|
||||
return (offset, now);
|
||||
}
|
||||
|
||||
Future<String> getMachineTz() async {
|
||||
return await FlutterTimezone.getLocalTimezone();
|
||||
}
|
||||
|
||||
List<String> getAvailableTz() {
|
||||
return tz.timeZoneDatabase.locations.keys.toList();
|
||||
}
|
21
lib/services/timezone/web.dart
Normal file
21
lib/services/timezone/web.dart
Normal file
@ -0,0 +1,21 @@
|
||||
import 'package:flutter_timezone/flutter_timezone.dart';
|
||||
import 'package:timezone/browser.dart' as tz;
|
||||
|
||||
Future<void> initializeTzdb() async {
|
||||
await tz.initializeTimeZone();
|
||||
}
|
||||
|
||||
(Duration offset, DateTime now) getTzInfo(String name) {
|
||||
final location = tz.getLocation(name);
|
||||
final now = tz.TZDateTime.now(location);
|
||||
final offset = now.timeZoneOffset;
|
||||
return (offset, now);
|
||||
}
|
||||
|
||||
Future<String> getMachineTz() async {
|
||||
return await FlutterTimezone.getLocalTimezone();
|
||||
}
|
||||
|
||||
List<String> getAvailableTz() {
|
||||
return tz.timeZoneDatabase.locations.keys.toList();
|
||||
}
|
@ -10,6 +10,7 @@ import 'package:gal/gal.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/pods/config.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:path/path.dart' show extension;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
@ -194,14 +195,18 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
// Get the image URL
|
||||
final imageUrl = '$serverUrl/files/${item.id}?original=true';
|
||||
final client = ref.watch(apiClientProvider);
|
||||
|
||||
// Create a temporary file to save the image
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
final filePath = '${tempDir.path}/${item.id}.${extension(item.name)}';
|
||||
|
||||
await Dio().download(imageUrl, filePath);
|
||||
await Gal.putImage(filePath);
|
||||
await client.download(
|
||||
'/files/${item.id}',
|
||||
filePath,
|
||||
queryParameters: {'original': true},
|
||||
);
|
||||
await Gal.putImage(filePath, album: 'Solar Network');
|
||||
|
||||
// Show success message
|
||||
scaffold.showSnackBar(
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <flutter_platform_alert/flutter_platform_alert_plugin.h>
|
||||
#include <flutter_timezone/flutter_timezone_plugin.h>
|
||||
#include <flutter_udid/flutter_udid_plugin.h>
|
||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||
#include <irondash_engine_context/irondash_engine_context_plugin.h>
|
||||
@ -31,6 +32,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) flutter_platform_alert_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterPlatformAlertPlugin");
|
||||
flutter_platform_alert_plugin_register_with_registrar(flutter_platform_alert_registrar);
|
||||
g_autoptr(FlPluginRegistrar) flutter_timezone_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterTimezonePlugin");
|
||||
flutter_timezone_plugin_register_with_registrar(flutter_timezone_registrar);
|
||||
g_autoptr(FlPluginRegistrar) flutter_udid_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterUdidPlugin");
|
||||
flutter_udid_plugin_register_with_registrar(flutter_udid_registrar);
|
||||
|
@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
bitsdojo_window_linux
|
||||
file_selector_linux
|
||||
flutter_platform_alert
|
||||
flutter_timezone
|
||||
flutter_udid
|
||||
flutter_webrtc
|
||||
irondash_engine_context
|
||||
|
@ -14,6 +14,7 @@ import firebase_core
|
||||
import firebase_messaging
|
||||
import flutter_inappwebview_macos
|
||||
import flutter_platform_alert
|
||||
import flutter_timezone
|
||||
import flutter_udid
|
||||
import flutter_webrtc
|
||||
import gal
|
||||
@ -43,6 +44,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
||||
FlutterPlatformAlertPlugin.register(with: registry.registrar(forPlugin: "FlutterPlatformAlertPlugin"))
|
||||
FlutterTimezonePlugin.register(with: registry.registrar(forPlugin: "FlutterTimezonePlugin"))
|
||||
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
|
||||
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
|
||||
GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin"))
|
||||
|
@ -1,4 +1,4 @@
|
||||
platform :osx, '10.15'
|
||||
platform :osx, '11.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
@ -384,10 +384,14 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
@ -423,10 +427,14 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
@ -593,7 +601,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
@ -730,7 +738,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@ -755,7 +763,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
|
32
pubspec.lock
32
pubspec.lock
@ -589,10 +589,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
sha256: "77f8e81d22d2a07d0dee2c62e1dda71dc1da73bf43bb2d45af09727406167964"
|
||||
sha256: ef9908739bdd9c476353d6adff72e88fd00c625f5b959ae23f7567bd5137db0a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.1.9"
|
||||
version: "10.2.0"
|
||||
file_selector_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -867,6 +867,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.28"
|
||||
flutter_popup_card:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_popup_card
|
||||
sha256: "71bca1521e3bae790162183d4dbfb77b84e11a9604e4b5f3b0edad6c5a1495cd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.6"
|
||||
flutter_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -888,6 +896,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_timezone:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_timezone
|
||||
sha256: "13b2109ad75651faced4831bf262e32559e44aa549426eab8a597610d385d934"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
flutter_udid:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -2138,6 +2154,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.8"
|
||||
timezone:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: timezone
|
||||
sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.1"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -2351,10 +2375,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
|
||||
sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.1.2"
|
||||
web:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -109,6 +109,9 @@ dependencies:
|
||||
qr_flutter: ^4.1.0
|
||||
flutter_otp_text_field: ^1.5.1+1
|
||||
palette_generator: ^0.3.3+7
|
||||
flutter_popup_card: ^0.0.6
|
||||
timezone: ^0.10.1
|
||||
flutter_timezone: ^4.1.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
||||
#include <flutter_platform_alert/flutter_platform_alert_plugin.h>
|
||||
#include <flutter_timezone/flutter_timezone_plugin_c_api.h>
|
||||
#include <flutter_udid/flutter_udid_plugin_c_api.h>
|
||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||
#include <gal/gal_plugin_c_api.h>
|
||||
@ -39,6 +40,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi"));
|
||||
FlutterPlatformAlertPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterPlatformAlertPlugin"));
|
||||
FlutterTimezonePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterTimezonePluginCApi"));
|
||||
FlutterUdidPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
|
||||
FlutterWebRTCPluginRegisterWithRegistrar(
|
||||
|
@ -9,6 +9,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
firebase_core
|
||||
flutter_inappwebview_windows
|
||||
flutter_platform_alert
|
||||
flutter_timezone
|
||||
flutter_udid
|
||||
flutter_webrtc
|
||||
gal
|
||||
|
Loading…
x
Reference in New Issue
Block a user