mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-30 20:56:53 +00:00
finish
This commit is contained in:
parent
21611e63c7
commit
f53ad044c1
|
@ -19,12 +19,14 @@
|
||||||
"connect": "Connect",
|
"connect": "Connect",
|
||||||
"domain": "Domain",
|
"domain": "Domain",
|
||||||
"saving": "Saving..",
|
"saving": "Saving..",
|
||||||
"nickname": "nickname",
|
"nickname": "Nickname",
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
"later": "I will setup it later",
|
"later": "I will setup it later",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"no_data": "No data"
|
"no_data": "No data",
|
||||||
|
"wait": "Wait",
|
||||||
|
"remove": "Remove"
|
||||||
},
|
},
|
||||||
"more": {
|
"more": {
|
||||||
"_comment": "'More' tab",
|
"_comment": "'More' tab",
|
||||||
|
@ -191,7 +193,6 @@
|
||||||
"23": "Enter a nickname and strong password",
|
"23": "Enter a nickname and strong password",
|
||||||
"finish": "Everything is initialized",
|
"finish": "Everything is initialized",
|
||||||
"checks": "Checks have been completed \n{} ouf of {}"
|
"checks": "Checks have been completed \n{} ouf of {}"
|
||||||
|
|
||||||
},
|
},
|
||||||
"modals": {
|
"modals": {
|
||||||
"_comment": "messages in modals",
|
"_comment": "messages in modals",
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
"later": "Настрою потом",
|
"later": "Настрою потом",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"details": "Детальная информация",
|
"details": "Детальная информация",
|
||||||
"no_data": "Нет данных"
|
"no_data": "Нет данных",
|
||||||
|
"wait": "Ожидайте",
|
||||||
|
"remove": "Удалить"
|
||||||
},
|
},
|
||||||
"more": {
|
"more": {
|
||||||
"_comment": "вкладка еще",
|
"_comment": "вкладка еще",
|
||||||
|
|
|
@ -6,6 +6,8 @@ PODS:
|
||||||
- Flutter
|
- Flutter
|
||||||
- path_provider (0.0.1):
|
- path_provider (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- share_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
- shared_preferences (0.0.1):
|
- shared_preferences (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- url_launcher (0.0.1):
|
- url_launcher (0.0.1):
|
||||||
|
@ -18,6 +20,7 @@ DEPENDENCIES:
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- package_info (from `.symlinks/plugins/package_info/ios`)
|
- package_info (from `.symlinks/plugins/package_info/ios`)
|
||||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||||
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
||||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||||
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||||
|
@ -31,6 +34,8 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/package_info/ios"
|
:path: ".symlinks/plugins/package_info/ios"
|
||||||
path_provider:
|
path_provider:
|
||||||
:path: ".symlinks/plugins/path_provider/ios"
|
:path: ".symlinks/plugins/path_provider/ios"
|
||||||
|
share_plus:
|
||||||
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
:path: ".symlinks/plugins/shared_preferences/ios"
|
:path: ".symlinks/plugins/shared_preferences/ios"
|
||||||
url_launcher:
|
url_launcher:
|
||||||
|
@ -43,6 +48,7 @@ SPEC CHECKSUMS:
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||||
|
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
||||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||||
|
|
|
@ -17,7 +17,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
// SchedulerBinding.instance.window.platformBrightness;
|
// SchedulerBinding.instance.window.platformBrightness;
|
||||||
// var isDark = platformBrightness == Brightness.dark;
|
// var isDark = platformBrightness == Brightness.dark;
|
||||||
var isDark = false;
|
var isDark = false;
|
||||||
|
var usersCubit = UsersCubit();
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
|
@ -31,8 +31,8 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
create: (_) => AppConfigCubit()..load(),
|
create: (_) => AppConfigCubit()..load(),
|
||||||
),
|
),
|
||||||
BlocProvider(create: (_) => ProvidersCubit()),
|
BlocProvider(create: (_) => ProvidersCubit()),
|
||||||
BlocProvider(create: (_) => UsersCubit()),
|
BlocProvider(create: (_) => usersCubit..load(), lazy: false),
|
||||||
BlocProvider(create: (_) => JobsCubit()),
|
BlocProvider(create: (_) => JobsCubit(usersCubit)),
|
||||||
],
|
],
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,6 +19,8 @@ class HiveConfig {
|
||||||
Hive.registerAdapter(HetznerDataBaseAdapter());
|
Hive.registerAdapter(HetznerDataBaseAdapter());
|
||||||
|
|
||||||
await Hive.openBox(BNames.appSettings);
|
await Hive.openBox(BNames.appSettings);
|
||||||
|
await Hive.openBox<User>(BNames.users);
|
||||||
|
|
||||||
var cipher = HiveAesCipher(await getEncriptedKey());
|
var cipher = HiveAesCipher(await getEncriptedKey());
|
||||||
|
|
||||||
await Hive.openBox(BNames.appConfig, encryptionCipher: cipher);
|
await Hive.openBox(BNames.appConfig, encryptionCipher: cipher);
|
||||||
|
@ -42,6 +44,7 @@ class BNames {
|
||||||
static String appConfig = 'appConfig';
|
static String appConfig = 'appConfig';
|
||||||
static String isDarkModeOn = 'isDarkModeOn';
|
static String isDarkModeOn = 'isDarkModeOn';
|
||||||
static String isOnbordingShowing = 'isOnbordingShowing';
|
static String isOnbordingShowing = 'isOnbordingShowing';
|
||||||
|
static String users = 'users';
|
||||||
|
|
||||||
static String appSettings = 'appSettings';
|
static String appSettings = 'appSettings';
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ class HetznerApi extends ApiMap {
|
||||||
var dbId = dbCreateResponse.data['volume']['id'];
|
var dbId = dbCreateResponse.data['volume']['id'];
|
||||||
|
|
||||||
var data = jsonDecode(
|
var data = jsonDecode(
|
||||||
'''{"name":"$domainName","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[$dbId], "networks":[],"user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-20.09 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword.hash} SALT=${rootUser.hashPassword.salt} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}''',
|
'''{"name":"$domainName","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[$dbId], "networks":[], "user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword.hash} SALT=${rootUser.hashPassword.salt} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}'''
|
||||||
);
|
);
|
||||||
|
|
||||||
Response serverCreateResponse = await client.post(
|
Response serverCreateResponse = await client.post(
|
||||||
|
|
|
@ -51,8 +51,9 @@ class ServerApi extends ApiMap {
|
||||||
'/createUser',
|
'/createUser',
|
||||||
options: Options(
|
options: Options(
|
||||||
headers: {
|
headers: {
|
||||||
"X-Username": user.login,
|
"X-User": user.login,
|
||||||
"X-Password": user.password,
|
"X-Password":
|
||||||
|
'\$6\$${user.hashPassword.salt}\$${user.hashPassword.hash}',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -68,4 +69,24 @@ class ServerApi extends ApiMap {
|
||||||
|
|
||||||
String get rootAddress =>
|
String get rootAddress =>
|
||||||
throw UnimplementedError('not used in with implementation');
|
throw UnimplementedError('not used in with implementation');
|
||||||
|
|
||||||
|
Future<bool> apply() async {
|
||||||
|
bool res;
|
||||||
|
Response response;
|
||||||
|
|
||||||
|
var client = await getClient();
|
||||||
|
try {
|
||||||
|
response = await client.get(
|
||||||
|
'/apply',
|
||||||
|
);
|
||||||
|
|
||||||
|
res = response.statusCode == HttpStatus.ok;
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(client);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,53 @@
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/jobs/job.dart';
|
import 'package:selfprivacy/logic/models/jobs/job.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/user.dart';
|
||||||
export 'package:provider/provider.dart';
|
export 'package:provider/provider.dart';
|
||||||
|
|
||||||
part 'jobs_state.dart';
|
part 'jobs_state.dart';
|
||||||
|
|
||||||
class JobsCubit extends Cubit<JobsState> {
|
class JobsCubit extends Cubit<JobsState> {
|
||||||
JobsCubit() : super(JobsState.emtpy());
|
JobsCubit(this.usersCubit) : super(JobsStateEmpty());
|
||||||
|
|
||||||
final api = ServerApi();
|
final api = ServerApi();
|
||||||
|
final UsersCubit usersCubit;
|
||||||
|
|
||||||
void addJob(Job job) {
|
void addJob(Job job) {
|
||||||
final newState = state.addJob(job);
|
var newJobsList = <Job>[];
|
||||||
emit(newState);
|
if (state is JobsStateWithJobs) {
|
||||||
|
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||||
|
}
|
||||||
|
newJobsList.add(job);
|
||||||
|
emit(JobsStateWithJobs(newJobsList));
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeJob(String id) {
|
void removeJob(String id) {
|
||||||
final newState = state.removeById(id);
|
final newState = (state as JobsStateWithJobs).removeById(id);
|
||||||
emit(newState);
|
emit(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> applyAll() async {
|
Future<void> applyAll() async {
|
||||||
for (var job in state.jobList) {
|
if (state is JobsStateWithJobs) {
|
||||||
|
var jobs = (state as JobsStateWithJobs).jobList;
|
||||||
|
emit(JobsStateLoading());
|
||||||
|
|
||||||
|
var newUsers = <User>[];
|
||||||
|
for (var job in jobs) {
|
||||||
if (job is CreateUserJob) {
|
if (job is CreateUserJob) {
|
||||||
// await api.createUser(job.user);
|
newUsers.add(job.user);
|
||||||
|
await api.createUser(job.user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit(JobsState.emtpy());
|
|
||||||
|
usersCubit.addUsers(newUsers);
|
||||||
|
await api.apply();
|
||||||
|
|
||||||
|
emit(JobsStateEmpty());
|
||||||
|
|
||||||
|
getIt<NavigationService>().navigator!.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,27 @@
|
||||||
part of 'jobs_cubit.dart';
|
part of 'jobs_cubit.dart';
|
||||||
|
|
||||||
class JobsState extends Equatable {
|
abstract class JobsState extends Equatable {
|
||||||
const JobsState(this.jobList);
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
final List<Job> jobList;
|
|
||||||
|
|
||||||
static JobsState emtpy() => JobsState([]);
|
|
||||||
|
|
||||||
bool get isEmpty => jobList.isEmpty;
|
|
||||||
|
|
||||||
JobsState addJob(Job job) {
|
|
||||||
var newJobsList = [...jobList];
|
|
||||||
newJobsList.add(job);
|
|
||||||
return JobsState(newJobsList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class JobsStateLoading extends JobsState {}
|
||||||
|
|
||||||
|
class JobsStateEmpty extends JobsState {}
|
||||||
|
|
||||||
|
class JobsStateWithJobs extends JobsState {
|
||||||
|
JobsStateWithJobs(this.jobList);
|
||||||
|
final List<Job> jobList;
|
||||||
|
|
||||||
JobsState removeById(String id) {
|
JobsState removeById(String id) {
|
||||||
var newJobsList = jobList.where((element) => element.id != id).toList();
|
var newJobsList = jobList.where((element) => element.id != id).toList();
|
||||||
return JobsState(newJobsList);
|
|
||||||
|
if (newJobsList.isEmpty) {
|
||||||
|
return JobsStateEmpty();
|
||||||
|
}
|
||||||
|
return JobsStateWithJobs(newJobsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => jobList;
|
List<Object?> get props => jobList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,35 @@
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:selfprivacy/config/hive_config.dart';
|
||||||
import 'package:selfprivacy/logic/models/user.dart';
|
import 'package:selfprivacy/logic/models/user.dart';
|
||||||
export 'package:provider/provider.dart';
|
export 'package:provider/provider.dart';
|
||||||
|
|
||||||
part 'users_state.dart';
|
part 'users_state.dart';
|
||||||
|
|
||||||
class UsersCubit extends Cubit<UsersState> {
|
class UsersCubit extends Cubit<UsersState> {
|
||||||
UsersCubit() : super(UsersState([]));
|
UsersCubit() : super(UsersState(<User>[]));
|
||||||
|
Box<User> box = Hive.box<User>(BNames.users);
|
||||||
|
|
||||||
void addUser(User user) {
|
void load() async {
|
||||||
var users = [...state.users];
|
var loadedUsers = box.values.toList();
|
||||||
users.add(user);
|
if (loadedUsers.isNotEmpty) {
|
||||||
|
emit(UsersState(loadedUsers));
|
||||||
emit(UsersState(users));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(User? user) {
|
void addUsers(List<User> users) async {
|
||||||
|
var newUserList = <User>[...state.users, ...users];
|
||||||
|
|
||||||
|
await box.addAll(users);
|
||||||
|
emit(UsersState(newUserList));
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(User user) async {
|
||||||
var users = [...state.users];
|
var users = [...state.users];
|
||||||
|
var index = users.indexOf(user);
|
||||||
users.remove(user);
|
users.remove(user);
|
||||||
|
await box.deleteAt(index);
|
||||||
|
|
||||||
emit(UsersState(users));
|
emit(UsersState(users));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,19 +23,16 @@ void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
|
|
||||||
runApp(
|
runApp(MyApp());
|
||||||
Localization(
|
|
||||||
child: BlocAndProviderConfig(
|
|
||||||
child: MyApp(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
AppSettingsState appSettings = context.watch<AppSettingsCubit>().state;
|
return Localization(
|
||||||
|
child: BlocAndProviderConfig(
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
var appSettings = context.watch<AppSettingsCubit>().state;
|
||||||
|
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle.light, // Manually changnig appbar color
|
value: SystemUiOverlayStyle.light, // Manually changnig appbar color
|
||||||
|
@ -54,10 +51,14 @@ class MyApp extends StatelessWidget {
|
||||||
Widget error = Text('...rendering error...');
|
Widget error = Text('...rendering error...');
|
||||||
if (widget is Scaffold || widget is Navigator)
|
if (widget is Scaffold || widget is Navigator)
|
||||||
error = Scaffold(body: Center(child: error));
|
error = Scaffold(body: Center(child: error));
|
||||||
ErrorWidget.builder = (FlutterErrorDetails errorDetails) => error;
|
ErrorWidget.builder =
|
||||||
|
(FlutterErrorDetails errorDetails) => error;
|
||||||
return widget!;
|
return widget!;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
lib/ui/components/brand_loader/brand_loader.dart
Normal file
21
lib/ui/components/brand_loader/brand_loader.dart
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
class BrandLoader {
|
||||||
|
static horizontal() => _HorizontalLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HorizontalLoader extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text('basis.wait'.tr()),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
LinearProgressIndicator(minHeight: 3),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/config/text_themes.dart';
|
import 'package:selfprivacy/config/text_themes.dart';
|
||||||
|
export 'package:selfprivacy/utils/extensions/text_extensions.dart';
|
||||||
|
|
||||||
enum TextType {
|
enum TextType {
|
||||||
h1, // right now only at onboarding and opened providers
|
h1, // right now only at onboarding and opened providers
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
import 'package:selfprivacy/config/brand_theme.dart';
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/brand_loader/brand_loader.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||||
|
|
||||||
class JobsContent extends StatelessWidget {
|
class JobsContent extends StatelessWidget {
|
||||||
|
@ -12,20 +15,22 @@ class JobsContent extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var jobs = context.watch<JobsCubit>().state;
|
return BlocBuilder<JobsCubit, JobsState>(
|
||||||
return ListView(
|
builder: (context, state) {
|
||||||
padding: paddingH15V0,
|
late final List<Widget> widgets;
|
||||||
children: [
|
if (state is JobsStateEmpty) {
|
||||||
SizedBox(height: 15),
|
widgets = [
|
||||||
Center(
|
SizedBox(height: 80),
|
||||||
child: BrandText.h2(
|
Center(child: BrandText.body1('jobs.empty'.tr())),
|
||||||
'jobs.title'.tr(),
|
];
|
||||||
),
|
} else if (state is JobsStateLoading) {
|
||||||
),
|
widgets = [
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 80),
|
||||||
if (jobs.isEmpty) BrandText.body1('jobs.empty'.tr()),
|
BrandLoader.horizontal(),
|
||||||
if (!jobs.isEmpty) ...[
|
];
|
||||||
...jobs.jobList
|
} else if (state is JobsStateWithJobs) {
|
||||||
|
widgets = [
|
||||||
|
...state.jobList
|
||||||
.map(
|
.map(
|
||||||
(j) => Row(
|
(j) => Row(
|
||||||
children: [
|
children: [
|
||||||
|
@ -48,7 +53,7 @@ class JobsContent extends StatelessWidget {
|
||||||
),
|
),
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
context.read<JobsCubit>().removeJob(j.id),
|
context.read<JobsCubit>().removeJob(j.id),
|
||||||
child: Text('Remove'),
|
child: Text('basis.remove'.tr()),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -59,8 +64,22 @@ class JobsContent extends StatelessWidget {
|
||||||
onPressed: () => context.read<JobsCubit>().applyAll(),
|
onPressed: () => context.read<JobsCubit>().applyAll(),
|
||||||
text: 'jobs.start'.tr(),
|
text: 'jobs.start'.tr(),
|
||||||
),
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return ListView(
|
||||||
|
padding: paddingH15V0,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 15),
|
||||||
|
Center(
|
||||||
|
child: BrandText.h2(
|
||||||
|
'jobs.title'.tr(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
...widgets
|
||||||
],
|
],
|
||||||
],
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,20 +42,18 @@ class _BrandFlashButtonState extends State<_BrandFlashButton>
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
late bool wasPrevStateIsEmpty;
|
bool wasPrevStateIsEmpty = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var hasNoJobs = context.watch<JobsCubit>().state.isEmpty;
|
|
||||||
wasPrevStateIsEmpty = hasNoJobs;
|
|
||||||
var icon = hasNoJobs ? Ionicons.flash_outline : Ionicons.flash;
|
|
||||||
|
|
||||||
return BlocListener<JobsCubit, JobsState>(
|
return BlocListener<JobsCubit, JobsState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (wasPrevStateIsEmpty && state.jobList.isNotEmpty) {
|
if (wasPrevStateIsEmpty && state is! JobsStateEmpty) {
|
||||||
wasPrevStateIsEmpty = false;
|
wasPrevStateIsEmpty = false;
|
||||||
_animationController.forward();
|
_animationController.forward();
|
||||||
} else if (!wasPrevStateIsEmpty && state.jobList.isEmpty) {
|
} else if (!wasPrevStateIsEmpty && state is JobsStateEmpty) {
|
||||||
|
wasPrevStateIsEmpty = true;
|
||||||
|
|
||||||
_animationController.reverse();
|
_animationController.reverse();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -73,6 +71,7 @@ class _BrandFlashButtonState extends State<_BrandFlashButton>
|
||||||
animation: _colorTween,
|
animation: _colorTween,
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
var v = _animationController.value;
|
var v = _animationController.value;
|
||||||
|
var icon = v > 0.5 ? Ionicons.flash : Ionicons.flash_outline;
|
||||||
return Transform.scale(
|
return Transform.scale(
|
||||||
scale: 1 + (v < 0.5 ? v : 1 - v) * 2,
|
scale: 1 + (v < 0.5 ? v : 1 - v) * 2,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
|
|
|
@ -82,7 +82,6 @@ class CpuChart extends StatelessWidget {
|
||||||
double appliedInterval,
|
double appliedInterval,
|
||||||
double value,
|
double value,
|
||||||
) {
|
) {
|
||||||
print(value);
|
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
return false;
|
return false;
|
||||||
} else if (value == 0) {
|
} else if (value == 0) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
part of 'users.dart';
|
part of 'users.dart';
|
||||||
|
|
||||||
class _User extends StatelessWidget {
|
class _User extends StatelessWidget {
|
||||||
const _User({Key? key, this.user}) : super(key: key);
|
const _User({Key? key, required this.user}) : super(key: key);
|
||||||
|
|
||||||
final User? user;
|
final User user;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
|
@ -24,12 +24,12 @@ class _User extends StatelessWidget {
|
||||||
width: 17,
|
width: 17,
|
||||||
height: 17,
|
height: 17,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: user!.color,
|
color: user.color,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
BrandText.h4(user!.login),
|
BrandText.h4(user.login),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -3,10 +3,10 @@ part of 'users.dart';
|
||||||
class _UserDetails extends StatelessWidget {
|
class _UserDetails extends StatelessWidget {
|
||||||
const _UserDetails({
|
const _UserDetails({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.user,
|
required this.user,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final User? user;
|
final User user;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -23,7 +23,7 @@ class _UserDetails extends StatelessWidget {
|
||||||
Container(
|
Container(
|
||||||
height: 200,
|
height: 200,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: user!.color,
|
color: user.color,
|
||||||
borderRadius: BorderRadius.vertical(
|
borderRadius: BorderRadius.vertical(
|
||||||
top: Radius.circular(20),
|
top: Radius.circular(20),
|
||||||
),
|
),
|
||||||
|
@ -116,7 +116,7 @@ class _UserDetails extends StatelessWidget {
|
||||||
horizontal: 15,
|
horizontal: 15,
|
||||||
),
|
),
|
||||||
child: BrandText.h1(
|
child: BrandText.h1(
|
||||||
user!.login,
|
user.login,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
)),
|
)),
|
||||||
|
@ -133,14 +133,14 @@ class _UserDetails extends StatelessWidget {
|
||||||
Container(
|
Container(
|
||||||
height: 40,
|
height: 40,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: BrandText.h4('${user!.login}@$domainName'),
|
child: BrandText.h4('${user.login}@$domainName'),
|
||||||
),
|
),
|
||||||
SizedBox(height: 14),
|
SizedBox(height: 14),
|
||||||
BrandText.small('basis.password'.tr()),
|
BrandText.small('basis.password'.tr()),
|
||||||
Container(
|
Container(
|
||||||
height: 40,
|
height: 40,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: BrandText.h4(user!.password),
|
child: BrandText.h4(user.password),
|
||||||
),
|
),
|
||||||
SizedBox(height: 24),
|
SizedBox(height: 24),
|
||||||
BrandDivider(),
|
BrandDivider(),
|
||||||
|
@ -148,7 +148,10 @@ class _UserDetails extends StatelessWidget {
|
||||||
BrandButton.emptyWithIconText(
|
BrandButton.emptyWithIconText(
|
||||||
title: 'users.send_regisration_data'.tr(),
|
title: 'users.send_regisration_data'.tr(),
|
||||||
icon: Icon(BrandIcons.share),
|
icon: Icon(BrandIcons.share),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
Share.share(
|
||||||
|
'login: ${user.login}, password: ${user.password}');
|
||||||
|
},
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
|
|
|
@ -17,6 +17,7 @@ import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
import 'package:selfprivacy/ui/helpers/modals.dart';
|
||||||
import 'package:selfprivacy/utils/ui_helpers.dart';
|
import 'package:selfprivacy/utils/ui_helpers.dart';
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
part 'fab.dart';
|
part 'fab.dart';
|
||||||
part 'new_user.dart';
|
part 'new_user.dart';
|
||||||
|
@ -33,7 +34,6 @@ class UsersPage extends StatelessWidget {
|
||||||
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized;
|
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized;
|
||||||
final users = usersCubitState.users;
|
final users = usersCubitState.users;
|
||||||
final isEmpty = usersCubitState.isEmpty;
|
final isEmpty = usersCubitState.isEmpty;
|
||||||
|
|
||||||
Widget child;
|
Widget child;
|
||||||
|
|
||||||
if (!isReady) {
|
if (!isReady) {
|
||||||
|
@ -48,7 +48,7 @@ class UsersPage extends StatelessWidget {
|
||||||
)
|
)
|
||||||
: ListView(
|
: ListView(
|
||||||
children: [
|
children: [
|
||||||
...users.map((user) => _User(user: user)),
|
...users.map((user) => _User(user: user)).toList(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
51
lib/utils/extensions/text_extensions.dart
Normal file
51
lib/utils/extensions/text_extensions.dart
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
extension TextExtension on Text {
|
||||||
|
Text withColor(Color color) => Text(
|
||||||
|
data!,
|
||||||
|
key: this.key,
|
||||||
|
strutStyle: this.strutStyle,
|
||||||
|
textAlign: this.textAlign,
|
||||||
|
textDirection: this.textDirection,
|
||||||
|
locale: this.locale,
|
||||||
|
softWrap: this.softWrap,
|
||||||
|
overflow: this.overflow,
|
||||||
|
textScaleFactor: this.textScaleFactor,
|
||||||
|
maxLines: this.maxLines,
|
||||||
|
semanticsLabel: this.semanticsLabel,
|
||||||
|
textWidthBasis: textWidthBasis ?? this.textWidthBasis,
|
||||||
|
style: this.style != null
|
||||||
|
? this.style!.copyWith(color: color)
|
||||||
|
: TextStyle(color: color),
|
||||||
|
);
|
||||||
|
|
||||||
|
Text copyWith({
|
||||||
|
Key? key,
|
||||||
|
StrutStyle? strutStyle,
|
||||||
|
TextAlign? textAlign,
|
||||||
|
TextDirection? textDirection,
|
||||||
|
Locale? locale,
|
||||||
|
bool? softWrap,
|
||||||
|
TextOverflow? overflow,
|
||||||
|
double? textScaleFactor,
|
||||||
|
int? maxLines,
|
||||||
|
String? semanticsLabel,
|
||||||
|
TextWidthBasis? textWidthBasis,
|
||||||
|
TextStyle? style,
|
||||||
|
}) {
|
||||||
|
return Text(data!,
|
||||||
|
key: key ?? this.key,
|
||||||
|
strutStyle: strutStyle ?? this.strutStyle,
|
||||||
|
textAlign: textAlign ?? this.textAlign,
|
||||||
|
textDirection: textDirection ?? this.textDirection,
|
||||||
|
locale: locale ?? this.locale,
|
||||||
|
softWrap: softWrap ?? this.softWrap,
|
||||||
|
overflow: overflow ?? this.overflow,
|
||||||
|
textScaleFactor: textScaleFactor ?? this.textScaleFactor,
|
||||||
|
maxLines: maxLines ?? this.maxLines,
|
||||||
|
semanticsLabel: semanticsLabel ?? this.semanticsLabel,
|
||||||
|
textWidthBasis: textWidthBasis ?? this.textWidthBasis,
|
||||||
|
style: style != null ? this.style?.merge(style) ?? style : this.style);
|
||||||
|
}
|
||||||
|
}
|
42
pubspec.lock
42
pubspec.lock
|
@ -651,6 +651,48 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
share_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: share_plus
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.4"
|
||||||
|
share_plus_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: share_plus_linux
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
|
share_plus_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: share_plus_macos
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
share_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: share_plus_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
|
share_plus_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: share_plus_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.4"
|
||||||
|
share_plus_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: share_plus_windows
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -31,6 +31,7 @@ dependencies:
|
||||||
package_info: ^2.0.0
|
package_info: ^2.0.0
|
||||||
pretty_dio_logger: ^1.1.1
|
pretty_dio_logger: ^1.1.1
|
||||||
provider: ^5.0.0
|
provider: ^5.0.0
|
||||||
|
share_plus: ^2.1.4
|
||||||
unicons: ^1.0.2
|
unicons: ^1.0.2
|
||||||
url_launcher: ^6.0.2
|
url_launcher: ^6.0.2
|
||||||
wakelock: ^0.5.0+2
|
wakelock: ^0.5.0+2
|
||||||
|
|
Loading…
Reference in a new issue