Skip to content

Commit

Permalink
Merge pull request #367 from vicolo-dev/release/0.6.0
Browse files Browse the repository at this point in the history
Update strings
  • Loading branch information
azeem-io authored Nov 8, 2024
2 parents 2ffc828 + c7abcd7 commit 5a610ce
Show file tree
Hide file tree
Showing 28 changed files with 516 additions and 98 deletions.
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
android:label="@string/app_name"
tools:replace="android:label"
android:name="${applicationName}"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
Expand Down
17 changes: 17 additions & 0 deletions lib/alarm/data/alarm_task_schemas.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:clock_app/alarm/types/alarm_task.dart';
import 'package:clock_app/alarm/widgets/tasks/math_task.dart';
import 'package:clock_app/alarm/widgets/tasks/memory_task.dart';
import 'package:clock_app/alarm/widgets/tasks/retype_task.dart';
import 'package:clock_app/alarm/widgets/tasks/sequence_task.dart';
import 'package:clock_app/settings/types/setting.dart';
Expand Down Expand Up @@ -98,4 +99,20 @@ Map<AlarmTaskType, AlarmTaskSchema> alarmTaskSchemasMap = {
return SequenceTask(onSolve: onSolve, settings: settings);
},
),
AlarmTaskType.memory: AlarmTaskSchema(
(context) => AppLocalizations.of(context)!.memoryTask,
SettingGroup("memorySettings",
(context) => AppLocalizations.of(context)!.memoryTask, [
SliderSetting(
"numberOfPairs",
(context) => AppLocalizations.of(context)!.numberOfPairsSetting,
3,
10,
3,
snapLength: 1),
]),
(onSolve, settings) {
return MemoryTask(onSolve: onSolve, settings: settings);
},
),
};
4 changes: 2 additions & 2 deletions lib/alarm/logic/alarm_reminder_notifications.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Future<void> createAlarmReminderNotification(
key: "alarm_skip",
label: 'Skip alarm${tasksRequired ? " (Solve tasks)" : ""}',
actionType:
tasksRequired ? ActionType.Default : ActionType.SilentAction,
tasksRequired ? ActionType.Default : ActionType.SilentBackgroundAction,
autoDismissible: true,
)
],
Expand Down Expand Up @@ -110,7 +110,7 @@ Future<void> createSnoozeNotification(int id, DateTime time) async {
key: "alarm_skip_snooze",
label: 'Dismiss alarm${tasksRequired ? " (Solve tasks)" : ""}',
actionType:
tasksRequired ? ActionType.Default : ActionType.SilentAction,
tasksRequired ? ActionType.Default : ActionType.SilentBackgroundAction,
autoDismissible: true,
)
],
Expand Down
46 changes: 26 additions & 20 deletions lib/alarm/screens/alarm_notification_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,28 +117,34 @@ class _AlarmNotificationScreenState extends State<AlarmNotificationScreen> {
children: [
if (_currentIndex <= 0)
Expanded(
flex: 1,
child: Column(
children: [
const Spacer(),
if (alarm.label.isNotEmpty)
flex: 2,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
children: [
const Spacer(),
if (alarm.label.isNotEmpty)
Text(
alarm.label,
style: Theme.of(context).textTheme.displayMedium,
textAlign: TextAlign.center,
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 8),
const DigitalClock(
// dateTime: Date,
horizontalAlignment: ElementAlignment.center,
shouldShowDate: false,
shouldShowSeconds: false,
),
const SizedBox(height: 8),
Text(
alarm.label,
style: Theme.of(context).textTheme.titleMedium,
"Alarm",
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 8),
const DigitalClock(
// dateTime: Date,
horizontalAlignment: ElementAlignment.center,
shouldShowDate: false,
shouldShowSeconds: false,
),
const SizedBox(height: 8),
Text(
"Alarm",
style: Theme.of(context).textTheme.headlineMedium,
),
],
],
),
),
),
Expanded(
Expand Down
4 changes: 4 additions & 0 deletions lib/alarm/types/alarm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -450,4 +450,8 @@ class Alarm extends CustomizableListItem {
'settings': _settings.valueToJson(),
'skippedTime': _skippedTime?.millisecondsSinceEpoch,
};

bool isEqualTo(Alarm other) {
return _time == other._time && _settings.isEqualTo(other._settings);
}
}
245 changes: 245 additions & 0 deletions lib/alarm/widgets/tasks/memory_task.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
import 'dart:async';
import 'dart:math';

import 'package:clock_app/common/widgets/card_container.dart';
import 'package:clock_app/settings/types/setting_group.dart';
import 'package:flutter/material.dart';

class MemoryTask extends StatefulWidget {
const MemoryTask({
super.key,
required this.onSolve,
required this.settings,
});

final VoidCallback onSolve;
final SettingGroup settings;

@override
State<MemoryTask> createState() => _MemoryTaskState();
}

class _MemoryTaskState extends State<MemoryTask> with TickerProviderStateMixin {
late final int numberOfPairs =
widget.settings.getSetting("numberOfPairs").value.toInt();

late List<CardModel> _cards;
CardModel? _firstCard;
bool _isWaiting = false;

@override
void initState() {
super.initState();
_initializeCards();
}

void _initializeCards() {
// Generate pairs of cards
List<int> cardValues = [
...List.generate(numberOfPairs, (index) => index + 1),
...List.generate(numberOfPairs, (index) => index + 1)
];
// cardValues.addAll(cardValues); // Duplicate for pairs
cardValues.shuffle(); // Shuffle the cards

_cards = cardValues
.map((value) => CardModel(value: value, isFlipped: false))
.toList();
}

void _onCardTap(CardModel card) {
if (_isWaiting || card.isFlipped) return;

setState(() {
card.isFlipped = true;
});

if (_firstCard == null) {
_firstCard = card;
} else {
if (_firstCard!.value == card.value) {
// Match found
_firstCard!.isCompleted = true;
card.isCompleted = true;
_firstCard = null;

if (_cards.every((card) => card.isFlipped)) {
// All cards are flipped
Future.delayed(const Duration(seconds: 1), () {
widget.onSolve();
});
}
} else {
// No match, flip back after delay
_isWaiting = true;
Future.delayed(const Duration(seconds: 1), () {
setState(() {
card.isFlipped = false;
_firstCard!.isFlipped = false;
_firstCard = null;
_isWaiting = false;
});
});
}
}
}

@override
Widget build(BuildContext context) {
ThemeData theme = Theme.of(context);
ColorScheme colorScheme = theme.colorScheme;
TextTheme textTheme = theme.textTheme;
int gridSize = (sqrt(_cards.length)).floor();

return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Text(
"Match card pairs",
style: textTheme.headlineMedium,
),
const SizedBox(height: 16.0),
SizedBox(
width: double.infinity,
// height: 512,
child: GridView.builder(
itemCount: _cards.length,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: gridSize,
),
itemBuilder: (context, index) {
CardModel card = _cards[index];
return GestureDetector(
key: ValueKey(card),
onTap: () => _onCardTap(card),
child: FlipCard(
isFlipped: card.isFlipped,
front: CardContainer(
margin: const EdgeInsets.all(4.0),
color: colorScheme.primary,
child: Center(
child: Text(
'?',
style: textTheme.displayMedium?.copyWith(
color: colorScheme.onPrimary,
),
),
),
),
back: CardContainer(
margin: const EdgeInsets.all(4.0),
color: card.isCompleted ? Colors.green : Colors.orangeAccent,
child: Center(
child: Text(
'${card.value}',
style: textTheme.displayMedium?.copyWith(
color: Colors.white,

),
),
),
),
),
);
},
),
),
],
),
);
}
}

class CardModel {
final int value;
bool isCompleted = false;
bool isFlipped;

CardModel({required this.value, this.isFlipped = false});
}

class FlipCard extends StatefulWidget {
final Widget front;
final Widget back;
final bool isFlipped;

const FlipCard({
super.key,
required this.front,
required this.back,
required this.isFlipped,
});

@override
State<FlipCard> createState() => _FlipCardState();
}

class _FlipCardState extends State<FlipCard>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;

@override
void initState() {
super.initState();

_controller = AnimationController(
duration: const Duration(milliseconds: 400),
vsync: this,
);

_animation = Tween<double>(begin: 0, end: 1).animate(_controller);

if (widget.isFlipped) {
_controller.value = 1;
}
}

@override
void didUpdateWidget(FlipCard oldWidget) {
super.didUpdateWidget(oldWidget);

if (widget.isFlipped != oldWidget.isFlipped) {
if (widget.isFlipped) {
_controller.forward();
} else {
_controller.reverse();
}
}
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
final angle = _animation.value * pi;
final transform = Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(angle);

Widget content;
if (angle <= pi / 2) {
content = widget.front;
} else {
content = widget.back;
transform.rotateY(pi);
}

return Transform(
transform: transform,
alignment: Alignment.center,
child: content,
);
},
);
}
}
4 changes: 2 additions & 2 deletions lib/alarm/widgets/tasks/sequence_task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import 'package:flutter/material.dart';

class SequenceTask extends StatefulWidget {
const SequenceTask({
Key? key,
super.key,
required this.onSolve,
required this.settings,
}) : super(key: key);
});

final VoidCallback onSolve;
final SettingGroup settings;
Expand Down
Loading

0 comments on commit 5a610ce

Please sign in to comment.