Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • android/random
1 result
Select Git revision
Show changes
Commits on Source (8)
Showing
with 191 additions and 60 deletions
image: ghcr.io/cirruslabs/flutter:latest
stages:
- update
- build-debug
- build-release
- release
- deploy
update:
stage: update
except:
- tags
script:
- flutter packages get
- flutter packages upgrade
interruptible: true
android:build-debug:
stage: build-debug
except:
- tags
- master
script:
# Flutter local configuration
- echo flutter.sdk=$FLUTTER_PATH > android/local.properties
......@@ -49,8 +40,6 @@ android:build-release:
- master
except:
- tags
dependencies:
- android:build-debug
script:
# Flutter local configuration
- echo flutter.sdk=$FLUTTER_PATH > android/local.properties
......
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=1.0.48
app.versionCode=49
app.versionName=1.0.51
app.versionCode=52
......@@ -12,6 +12,7 @@
"api_page_title": "API",
"settings_title": "Settings",
"settings_label_theme": "Theme mode",
"settings_label_api_url": "API URL:",
"settings_label_security_token": "Security token:",
"settings_label_interface_type": "Interface type:",
......
......@@ -12,6 +12,7 @@
"api_page_title": "API",
"settings_title": "Paramètres",
"settings_label_theme": "Thème de couleurs",
"settings_label_api_url": "URL de l'API :",
"settings_label_security_token": "Jeton de sécurité :",
"settings_label_interface_type": "Type d'interface :",
......
......@@ -62,7 +62,10 @@ class Menu {
];
static Widget getPageWidget(int pageIndex) {
return Menu.items.elementAt(pageIndex).page;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Menu.items.elementAt(pageIndex).page,
);
}
static List<BottomNavigationBarItem> getMenuItems() {
......
......@@ -4,6 +4,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:random/models/api_failure.dart';
import 'package:random/models/api_data.dart';
import 'package:random/repository/api.dart';
import 'package:random/utils/tools.dart';
part 'api_state.dart';
......@@ -27,7 +28,7 @@ class ApiDataCubit extends HydratedCubit<ApiDataState> {
}
}
}
print('emit new state: $stateAsString');
printlog('emit new state: $stateAsString');
emit(state);
}
......@@ -41,7 +42,7 @@ class ApiDataCubit extends HydratedCubit<ApiDataState> {
} on ApiFailure catch (err) {
customEmit(ApiDataFetchError(failure: err));
} catch (err) {
print("Error (fetchApiData): $err");
printlog("Error (fetchApiData): $err");
}
return ApiData.fromJson({});
}
......
......@@ -16,15 +16,12 @@ class ApiDataFetchInitial extends ApiDataState {}
class ApiDataFetchLoading extends ApiDataState {}
class ApiDataFetchLoaded extends ApiDataState {
@override
final ApiData data;
const ApiDataFetchLoaded({
required this.data,
required super.data,
});
@override
List<Object> get props => [data];
List<Object> get props => [data!];
}
class ApiDataFetchError extends ApiDataState {
......
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
part 'theme_state.dart';
class ThemeCubit extends HydratedCubit<ThemeModeState> {
ThemeCubit() : super(const ThemeModeState());
void getTheme(ThemeModeState state) {
emit(state);
}
@override
ThemeModeState? fromJson(Map<String, dynamic> json) {
switch (json['themeMode']) {
case 'ThemeMode.dark':
return const ThemeModeState(themeMode: ThemeMode.dark);
case 'ThemeMode.light':
return const ThemeModeState(themeMode: ThemeMode.light);
case 'ThemeMode.system':
default:
return const ThemeModeState(themeMode: ThemeMode.system);
}
}
@override
Map<String, String>? toJson(ThemeModeState state) {
return <String, String>{'themeMode': state.themeMode.toString()};
}
}
part of 'theme_cubit.dart';
@immutable
class ThemeModeState extends Equatable {
const ThemeModeState({
this.themeMode,
});
final ThemeMode? themeMode;
@override
List<Object?> get props => <Object?>[
themeMode,
];
}
......@@ -8,11 +8,12 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.dart';
import 'package:random/config/theme.dart';
import 'package:random/cubit/api_cubit.dart';
import 'package:random/cubit/bottom_nav_cubit.dart';
import 'package:random/cubit/data_cubit.dart';
import 'package:random/cubit/game_cubit.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/cubit/api_cubit.dart';
import 'package:random/cubit/theme_cubit.dart';
import 'package:random/repository/api.dart';
import 'package:random/network/api.dart';
import 'package:random/ui/skeleton.dart';
......@@ -48,10 +49,6 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
BlocProvider<DataCubit>(create: (context) => DataCubit()),
BlocProvider<GameCubit>(create: (context) => GameCubit()),
BlocProvider<ApiDataCubit>(
create: (context) => ApiDataCubit(
apiRepository: ApiRepository(
......@@ -59,16 +56,26 @@ class MyApp extends StatelessWidget {
),
)..fetchApiData(),
),
BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
BlocProvider<DataCubit>(create: (context) => DataCubit()),
BlocProvider<GameCubit>(create: (context) => GameCubit()),
BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
],
child: MaterialApp(
child: BlocBuilder<ThemeCubit, ThemeModeState>(
builder: (BuildContext context, ThemeModeState state) {
return MaterialApp(
title: 'Random application',
theme: appTheme,
theme: lightTheme,
darkTheme: darkTheme,
themeMode: state.themeMode,
home: const SkeletonScreen(),
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
debugShowCheckedModeBanner: false,
),
);
}),
);
}
}
......@@ -3,6 +3,7 @@ import 'dart:math';
import 'package:random/models/game/game_board.dart';
import 'package:random/models/game/game_cell.dart';
import 'package:random/models/game/game_settings.dart';
import 'package:random/utils/tools.dart';
class Game {
GameBoard board;
......@@ -88,7 +89,7 @@ class Game {
void dump() {
GameBoard.printGrid(board.cells);
print(settings.toJson());
print(toJson());
printlog(settings.toString());
printlog(toString());
}
}
......@@ -2,6 +2,7 @@ import 'dart:math';
import 'package:random/models/game/game_cell.dart';
import 'package:random/models/game/game_settings.dart';
import 'package:random/utils/tools.dart';
class GameBoard {
final List<List<GameCell>> cells;
......@@ -36,17 +37,17 @@ class GameBoard {
}
static printGrid(List<List<GameCell>> cells) {
print('');
print('-------');
printlog('');
printlog('-------');
for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
String row = '';
for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
row += cells[rowIndex][colIndex].value.toString();
}
print(row);
printlog(row);
}
print('-------');
print('');
printlog('-------');
printlog('');
}
@override
......
......@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:dio/dio.dart';
import 'package:random/models/api_failure.dart';
import 'package:random/utils/tools.dart';
class ApiService {
final Dio _dio = Dio();
......@@ -12,15 +13,15 @@ class ApiService {
Future<Response?> getData() async {
String url = '$baseUrl/get.php';
try {
print('fetching api data... $url');
printlog('fetching api data... $url');
final Response response = await _dio.get(url);
print('ok got api response.');
print(response);
printlog('ok got api response.');
printlog(response.toString());
return response;
} on SocketException {
throw const ApiFailure(message: 'Failed to reach API endpoint.');
} catch (err) {
print("Error (getData): $err");
printlog("Error (getData): $err");
throw ApiFailure(message: "$err");
}
}
......
import 'package:random/models/api_data.dart';
import 'package:random/network/api.dart';
import 'package:random/utils/tools.dart';
class ApiRepository {
const ApiRepository({required this.apiService});
......@@ -7,15 +8,15 @@ class ApiRepository {
final ApiService apiService;
Future<ApiData> getApiData() async {
print('(getApiData) delayed API call...');
printlog('(getApiData) delayed API call...');
final response = await Future.delayed(const Duration(milliseconds: 1000))
.then((value) => apiService.getData());
if (response != null) {
print('(getApiData) got api response');
print(response.data);
printlog('(getApiData) got api response');
printlog(response.data);
return ApiData.fromJson(response.data);
}
print('(getApiData) failed');
printlog('(getApiData) failed');
return ApiData.fromJson({});
}
}
......@@ -25,7 +25,7 @@ class _GamePageState extends State<GamePage> {
gameCubit.updateGameState(Game.createNew());
},
icon: const Icon(UniconsSolid.star),
color: Colors.white,
color: Theme.of(context).colorScheme.primary,
)
];
......@@ -39,7 +39,7 @@ class _GamePageState extends State<GamePage> {
setState(() {});
},
icon: const Icon(UniconsLine.exit),
color: Colors.white,
color: Theme.of(context).colorScheme.primary,
));
}
......
import 'package:flutter/material.dart';
import 'package:random/ui/painters/graph_painter.dart';
import 'package:random/utils/tools.dart';
class GraphPage extends StatefulWidget {
const GraphPage({super.key});
......@@ -33,7 +34,7 @@ class _GraphPageState extends State<GraphPage> {
onTapUp: (details) {
double xTap = details.localPosition.dx;
double yTap = details.localPosition.dy;
print('[$xTap,$yTap]');
printlog('[$xTap,$yTap]');
},
child: Container(
margin: const EdgeInsets.all(4),
......
......@@ -6,6 +6,7 @@ import 'package:random/models/game/game.dart';
import 'package:random/models/game/game_settings.dart';
import 'package:random/ui/painters/cell_painter.dart';
import 'package:random/ui/widgets/game/game_score.dart';
import 'package:random/utils/tools.dart';
class GameBoardWidget extends StatefulWidget {
const GameBoardWidget({
......@@ -168,11 +169,11 @@ class _GameBoardWidget extends State<GameBoardWidget> with TickerProviderStateMi
int x = (xTap / widgetWidth * columnsCount).toInt();
int y = (yTap / widgetHeight * rowsCount).toInt();
print('[$x,$y]');
printlog('[$x,$y]');
removeCell(context, x, y);
} else {
print('animation in progress...');
printlog('animation in progress...');
}
},
);
......
......@@ -6,6 +6,7 @@ import 'package:unicons/unicons.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/config/theme.dart';
import 'package:random/models/interface_type.dart';
import 'package:random/ui/widgets/theme_card.dart';
class SettingsForm extends StatefulWidget {
const SettingsForm({super.key});
......@@ -54,6 +55,35 @@ class _SettingsFormState extends State<SettingsForm> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
// Light/dark theme
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text('settings_label_theme').tr(),
const Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ThemeCard(
mode: ThemeMode.system,
icon: UniconsLine.cog,
),
ThemeCard(
mode: ThemeMode.light,
icon: UniconsLine.sun,
),
ThemeCard(
mode: ThemeMode.dark,
icon: UniconsLine.moon,
)
],
),
],
),
const SizedBox(height: 16),
const Text('settings_label_api_url').tr(),
TextFormField(
controller: apiUrlController,
......@@ -61,7 +91,9 @@ class _SettingsFormState extends State<SettingsForm> {
border: UnderlineInputBorder(),
),
),
const SizedBox(height: 16),
const Text('settings_label_security_token').tr(),
TextFormField(
controller: securityTokenController,
......@@ -69,7 +101,9 @@ class _SettingsFormState extends State<SettingsForm> {
border: UnderlineInputBorder(),
),
),
const SizedBox(height: 16),
const Text('settings_label_interface_type').tr(),
ToggleButtons(
direction: Axis.horizontal,
......
......@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:unicons/unicons.dart';
import 'package:random/utils/picture_storage.dart';
import 'package:random/utils/tools.dart';
class TakePictureWidget extends StatefulWidget {
const TakePictureWidget({super.key});
......@@ -71,14 +72,14 @@ class TakePictureWidgetState extends State<TakePictureWidget> {
try {
if ((controller != null) && (controller!.value.isInitialized)) {
final XFile image = await controller!.takePicture();
print('image.path: ${image.path}');
printlog('image.path: ${image.path}');
debug.add('image.path: ${image.path}');
File savedFile = await storage!.writeCounter(File(image.path));
debug.add('image.path: ${image.path}');
String imagePath = savedFile.path;
print('imagePath: $imagePath');
printlog('imagePath: $imagePath');
debug.add('imagePath: $imagePath');
previousImages.add(imagePath);
......@@ -88,7 +89,7 @@ class TakePictureWidgetState extends State<TakePictureWidget> {
debug.add('error: $e');
setState(() {});
print(e);
printlog(e.toString());
}
},
),
......
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:random/cubit/theme_cubit.dart';
class ThemeCard extends StatelessWidget {
const ThemeCard({
super.key,
required this.mode,
required this.icon,
});
final IconData icon;
final ThemeMode mode;
@override
Widget build(BuildContext context) {
return BlocBuilder<ThemeCubit, ThemeModeState>(
builder: (BuildContext context, ThemeModeState state) {
return Card(
elevation: 2,
shadowColor: Theme.of(context).colorScheme.shadow,
color: state.themeMode == mode
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.surface,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
margin: const EdgeInsets.all(5),
child: InkWell(
onTap: () => BlocProvider.of<ThemeCubit>(context).getTheme(
ThemeModeState(themeMode: mode),
),
borderRadius: const BorderRadius.all(Radius.circular(12)),
child: Icon(
icon,
size: 32,
color:
state.themeMode != mode ? Theme.of(context).colorScheme.primary : Colors.white,
),
),
);
});
}
}