Compare commits
No commits in common. "3ff136f758e4059ce662ae5f3cb50b84c1208c73" and "4d3de751f371b82a30eccda9aaaf5bf208026529" have entirely different histories.
3ff136f758
...
4d3de751f3
|
@ -39,14 +39,5 @@
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".StopAlarm"
|
|
||||||
android:exported="true"
|
|
||||||
android:process=":remote" />
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".AlarmService"
|
|
||||||
android:exported="false" />
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -1,155 +0,0 @@
|
||||||
package com.example.fmassive
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.*
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.media.AudioAttributes
|
|
||||||
import android.media.MediaPlayer
|
|
||||||
import android.media.MediaPlayer.OnPreparedListener
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.*
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
|
||||||
class AlarmService : Service(), OnPreparedListener {
|
|
||||||
private var mediaPlayer: MediaPlayer? = null
|
|
||||||
private var vibrator: Vibrator? = null
|
|
||||||
|
|
||||||
private fun getBuilder(): NotificationCompat.Builder {
|
|
||||||
val context = applicationContext
|
|
||||||
val contentIntent = Intent(context, MainActivity::class.java)
|
|
||||||
val pendingContent =
|
|
||||||
PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
val addBroadcast = Intent(MainActivity.ADD_BROADCAST).apply {
|
|
||||||
setPackage(context.packageName)
|
|
||||||
}
|
|
||||||
val pendingAdd =
|
|
||||||
PendingIntent.getBroadcast(context, 0, addBroadcast, PendingIntent.FLAG_MUTABLE)
|
|
||||||
val stopBroadcast = Intent(MainActivity.STOP_BROADCAST)
|
|
||||||
stopBroadcast.setPackage(context.packageName)
|
|
||||||
val pendingStop =
|
|
||||||
PendingIntent.getBroadcast(context, 0, stopBroadcast, PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
return NotificationCompat.Builder(context, MainActivity.CHANNEL_ID_PENDING)
|
|
||||||
.setSmallIcon(R.drawable.ic_baseline_hourglass_bottom_24).setContentTitle("Resting")
|
|
||||||
.setContentIntent(pendingContent)
|
|
||||||
.addAction(R.drawable.ic_baseline_stop_24, "Stop", pendingStop)
|
|
||||||
.addAction(R.drawable.ic_baseline_stop_24, "Add 1 min", pendingAdd)
|
|
||||||
.setDeleteIntent(pendingStop)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("Range")
|
|
||||||
private fun getSettings(): Settings {
|
|
||||||
val db = DatabaseHelper(applicationContext).readableDatabase
|
|
||||||
val cursor = db.rawQuery("SELECT sound, no_sound, vibrate FROM settings", null)
|
|
||||||
cursor.moveToFirst()
|
|
||||||
val sound = cursor.getString(cursor.getColumnIndex("sound"))
|
|
||||||
val noSound = cursor.getInt(cursor.getColumnIndex("no_sound")) == 1
|
|
||||||
val vibrate = cursor.getInt(cursor.getColumnIndex("vibrate")) == 1
|
|
||||||
Log.d("AlarmService", "vibrate=$vibrate")
|
|
||||||
cursor.close()
|
|
||||||
return Settings(sound, noSound, vibrate)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun playSound(settings: Settings) {
|
|
||||||
if (settings.sound == null && !settings.noSound) {
|
|
||||||
Log.d("AlarmService", "Playing default alarm sound...")
|
|
||||||
mediaPlayer = MediaPlayer.create(applicationContext, R.raw.argon)
|
|
||||||
mediaPlayer?.start()
|
|
||||||
mediaPlayer?.setOnCompletionListener { vibrator?.cancel() }
|
|
||||||
} else if (settings.sound != null && !settings.noSound) {
|
|
||||||
Log.d("AlarmService", "Playing custom alarm sound ${settings.sound}...")
|
|
||||||
mediaPlayer = MediaPlayer().apply {
|
|
||||||
setAudioAttributes(
|
|
||||||
AudioAttributes.Builder()
|
|
||||||
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
|
||||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
setDataSource(applicationContext, Uri.parse(settings.sound))
|
|
||||||
prepare()
|
|
||||||
start()
|
|
||||||
setOnCompletionListener { vibrator?.cancel() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doNotify(): Notification {
|
|
||||||
Log.d("AlarmService", "doNotify")
|
|
||||||
val alarmsChannel = NotificationChannel(
|
|
||||||
CHANNEL_ID_DONE,
|
|
||||||
CHANNEL_ID_DONE,
|
|
||||||
NotificationManager.IMPORTANCE_HIGH
|
|
||||||
)
|
|
||||||
alarmsChannel.description = "Alarms for rest timers."
|
|
||||||
alarmsChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
|
|
||||||
alarmsChannel.setSound(null, null)
|
|
||||||
val manager = applicationContext.getSystemService(
|
|
||||||
NotificationManager::class.java
|
|
||||||
)
|
|
||||||
manager.createNotificationChannel(alarmsChannel)
|
|
||||||
val builder = getBuilder()
|
|
||||||
val context = applicationContext
|
|
||||||
val finishIntent = Intent(context, StopAlarm::class.java)
|
|
||||||
val finishPending = PendingIntent.getActivity(
|
|
||||||
context, 0, finishIntent, PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
builder.setContentText("Timer finished.").setProgress(0, 0, false)
|
|
||||||
.setAutoCancel(true).setOngoing(true)
|
|
||||||
.setContentIntent(finishPending).setChannelId(CHANNEL_ID_DONE)
|
|
||||||
.setCategory(NotificationCompat.CATEGORY_ALARM).priority =
|
|
||||||
NotificationCompat.PRIORITY_HIGH
|
|
||||||
val notification = builder.build()
|
|
||||||
manager.notify(NOTIFICATION_ID_DONE, notification)
|
|
||||||
manager.cancel(MainActivity.NOTIFICATION_ID_PENDING)
|
|
||||||
return notification
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("Recycle")
|
|
||||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
|
||||||
Log.d("AlarmService", "onStartCommand")
|
|
||||||
val notification = doNotify()
|
|
||||||
startForeground(NOTIFICATION_ID_DONE, notification)
|
|
||||||
val settings = getSettings()
|
|
||||||
playSound(settings)
|
|
||||||
if (!settings.vibrate) return START_STICKY
|
|
||||||
val pattern = longArrayOf(0, 300, 1300, 300, 1300, 300)
|
|
||||||
vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
||||||
val vibratorManager =
|
|
||||||
getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
|
||||||
vibratorManager.defaultVibrator
|
|
||||||
} else {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
getSystemService(VIBRATOR_SERVICE) as Vibrator
|
|
||||||
}
|
|
||||||
val audioAttributes = AudioAttributes.Builder()
|
|
||||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
|
||||||
.setUsage(AudioAttributes.USAGE_ALARM)
|
|
||||||
.build()
|
|
||||||
vibrator!!.vibrate(VibrationEffect.createWaveform(pattern, 1), audioAttributes)
|
|
||||||
return START_STICKY
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepared(player: MediaPlayer) {
|
|
||||||
player.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
mediaPlayer?.stop()
|
|
||||||
mediaPlayer?.release()
|
|
||||||
vibrator?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val CHANNEL_ID_DONE = "Alarm"
|
|
||||||
const val NOTIFICATION_ID_DONE = 2
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package com.example.fmassive
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.database.sqlite.SQLiteDatabase
|
|
||||||
import android.database.sqlite.SQLiteOpenHelper
|
|
||||||
|
|
||||||
class DatabaseHelper(context: Context) :
|
|
||||||
SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
|
|
||||||
companion object {
|
|
||||||
private const val DATABASE_NAME = "massive.db"
|
|
||||||
private const val DATABASE_VERSION = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(db: SQLiteDatabase) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,14 +19,16 @@ import io.flutter.plugin.common.MethodChannel
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
class MainActivity : FlutterActivity() {
|
class MainActivity : FlutterActivity() {
|
||||||
|
private val CHANNEL = "com.massive/android"
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||||
super.configureFlutterEngine(flutterEngine)
|
super.configureFlutterEngine(flutterEngine)
|
||||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, FLUTTER_CHANNEL).setMethodCallHandler {
|
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
|
||||||
call, result ->
|
call, result ->
|
||||||
if (call.method == "timer") {
|
if (call.method == "timer") {
|
||||||
val args = call.arguments as ArrayList<*>
|
val args = call.arguments as ArrayList<*>
|
||||||
timer(args[0] as Int)
|
timer(args[0] as Long)
|
||||||
} else {
|
} else {
|
||||||
result.notImplemented()
|
result.notImplemented()
|
||||||
}
|
}
|
||||||
|
@ -40,7 +42,7 @@ class MainActivity : FlutterActivity() {
|
||||||
private val stopReceiver = object : BroadcastReceiver() {
|
private val stopReceiver = object : BroadcastReceiver() {
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
Log.d("MainActivity", "Received stop broadcast intent")
|
Log.d("AlarmModule", "Received stop broadcast intent")
|
||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,51 +59,59 @@ class MainActivity : FlutterActivity() {
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
fun add() {
|
fun add() {
|
||||||
Log.d("MainActivity", "Add 1 min to alarm.")
|
Log.d("AlarmModule", "Add 1 min to alarm.")
|
||||||
countdownTimer?.cancel()
|
countdownTimer?.cancel()
|
||||||
val newMs = if (running) currentMs.toInt().plus(60000) else 60000
|
val newMs = if (running) currentMs.toInt().plus(60000) else 60000
|
||||||
countdownTimer = getTimer(newMs)
|
countdownTimer = getTimer(newMs.toLong())
|
||||||
countdownTimer?.start()
|
countdownTimer?.start()
|
||||||
running = true
|
running = true
|
||||||
val manager = getManager()
|
//val manager = getManager()
|
||||||
manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
|
//manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
|
||||||
val intent = Intent(context, AlarmService::class.java)
|
//val intent = Intent(context, AlarmService::class.java)
|
||||||
context.stopService(intent)
|
//context.stopService(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
fun stop() {
|
fun stop() {
|
||||||
Log.d("MainActivity", "Stop alarm.")
|
Log.d("AlarmModule", "Stop alarm.")
|
||||||
countdownTimer?.cancel()
|
countdownTimer?.cancel()
|
||||||
running = false
|
running = false
|
||||||
val intent = Intent(context, AlarmService::class.java)
|
//val intent = Intent(context, AlarmService::class.java)
|
||||||
context.stopService(intent)
|
//reactApplicationContext?.stopService(intent)
|
||||||
val manager = getManager()
|
//val manager = getManager()
|
||||||
manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
|
//manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
|
||||||
manager.cancel(NOTIFICATION_ID_PENDING)
|
//manager.cancel(NOTIFICATION_ID_PENDING)
|
||||||
|
//val params = Arguments.createMap().apply {
|
||||||
|
// putString("minutes", "00")
|
||||||
|
// putString("seconds", "00")
|
||||||
|
//}
|
||||||
|
//reactApplicationContext
|
||||||
|
// .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||||
|
// .emit("tick", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
fun timer(milliseconds: Int) {
|
fun timer(milliseconds: Long) {
|
||||||
context.registerReceiver(stopReceiver, IntentFilter(STOP_BROADCAST))
|
context.registerReceiver(stopReceiver, IntentFilter(STOP_BROADCAST))
|
||||||
context.registerReceiver(addReceiver, IntentFilter(ADD_BROADCAST))
|
context.registerReceiver(addReceiver, IntentFilter(ADD_BROADCAST))
|
||||||
Log.d("MainActivity", "Queue alarm for $milliseconds delay")
|
Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
|
||||||
val manager = getManager()
|
//val manager = getManager()
|
||||||
manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
|
//manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
|
||||||
val intent = Intent(context, AlarmService::class.java)
|
//val intent = Intent(reactApplicationContext, AlarmService::class.java)
|
||||||
context.stopService(intent)
|
//reactApplicationContext.stopService(intent)
|
||||||
countdownTimer?.cancel()
|
countdownTimer?.cancel()
|
||||||
countdownTimer = getTimer(milliseconds)
|
countdownTimer = getTimer(milliseconds)
|
||||||
countdownTimer?.start()
|
countdownTimer?.start()
|
||||||
running = true
|
running = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
private fun getTimer(
|
private fun getTimer(
|
||||||
endMs: Int,
|
endMs: Long,
|
||||||
): CountDownTimer {
|
): CountDownTimer {
|
||||||
val builder = getBuilder()
|
val builder = getBuilder()
|
||||||
return object : CountDownTimer(endMs.toLong(), 1000) {
|
return object : CountDownTimer(endMs.toLong(), 1000) {
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
override fun onTick(current: Long) {
|
override fun onTick(current: Long) {
|
||||||
currentMs = current
|
currentMs = current
|
||||||
val seconds =
|
val seconds =
|
||||||
|
@ -113,13 +123,27 @@ class MainActivity : FlutterActivity() {
|
||||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS).priority =
|
.setCategory(NotificationCompat.CATEGORY_PROGRESS).priority =
|
||||||
NotificationCompat.PRIORITY_LOW
|
NotificationCompat.PRIORITY_LOW
|
||||||
val manager = getManager()
|
val manager = getManager()
|
||||||
Log.d("MainActivity", "current=$current")
|
Log.d("AlarmModule", "Notify $NOTIFICATION_ID_PENDING")
|
||||||
manager.notify(NOTIFICATION_ID_PENDING, builder.build())
|
manager.notify(NOTIFICATION_ID_PENDING, builder.build())
|
||||||
|
//val params = Arguments.createMap().apply {
|
||||||
|
// putString("minutes", minutes)
|
||||||
|
// putString("seconds", seconds)
|
||||||
|
//}
|
||||||
|
//reactApplicationContext
|
||||||
|
// .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||||
|
// .emit("tick", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
override fun onFinish() {
|
override fun onFinish() {
|
||||||
Log.d("MainActivity", "Finish")
|
//val context = reactApplicationContext
|
||||||
context.startForegroundService(Intent(context, AlarmService::class.java))
|
//context.startForegroundService(Intent(context, AlarmService::class.java))
|
||||||
|
//context
|
||||||
|
// .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||||
|
// .emit("finish", Arguments.createMap().apply {
|
||||||
|
// putString("minutes", "00")
|
||||||
|
// putString("seconds", "00")
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,6 +190,5 @@ class MainActivity : FlutterActivity() {
|
||||||
const val ADD_BROADCAST = "add-timer-event"
|
const val ADD_BROADCAST = "add-timer-event"
|
||||||
const val CHANNEL_ID_PENDING = "Timer"
|
const val CHANNEL_ID_PENDING = "Timer"
|
||||||
const val NOTIFICATION_ID_PENDING = 1
|
const val NOTIFICATION_ID_PENDING = 1
|
||||||
const val FLUTTER_CHANNEL = "com.massive/android"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
package com.example.fmassive
|
|
||||||
|
|
||||||
class Settings(val sound: String?, val noSound: Boolean, val vibrate: Boolean)
|
|
|
@ -1,22 +0,0 @@
|
||||||
package com.example.fmassive
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
|
|
||||||
class StopAlarm : Activity() {
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O_MR1)
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
Log.d("AlarmActivity", "Call to AlarmActivity")
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
val context = applicationContext
|
|
||||||
context.stopService(Intent(context, AlarmService::class.java))
|
|
||||||
savedInstanceState.apply { setShowWhenLocked(true) }
|
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
context.startActivity(intent)
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
|
@ -1,12 +1,10 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:fmassive/gym_set.dart';
|
import 'package:fmassive/gym_set.dart';
|
||||||
import 'package:fmassive/main.dart';
|
|
||||||
import 'package:moor/ffi.dart';
|
import 'package:moor/ffi.dart';
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
import 'settings.dart';
|
import 'settings.dart';
|
||||||
|
|
||||||
part 'database.g.dart';
|
part 'database.g.dart';
|
||||||
|
@ -22,8 +20,6 @@ class MyDatabase extends _$MyDatabase {
|
||||||
MigrationStrategy get migration => MigrationStrategy(
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
onCreate: (Migrator m) async {
|
onCreate: (Migrator m) async {
|
||||||
await m.createAll();
|
await m.createAll();
|
||||||
var data = await db.select(db.settings).get();
|
|
||||||
if (data.isEmpty) await db.into(db.settings).insert(defaultSettings);
|
|
||||||
},
|
},
|
||||||
onUpgrade: (Migrator m, int from, int to) async {
|
onUpgrade: (Migrator m, int from, int to) async {
|
||||||
// no migrations yet
|
// no migrations yet
|
||||||
|
@ -33,9 +29,8 @@ class MyDatabase extends _$MyDatabase {
|
||||||
|
|
||||||
LazyDatabase _openConnection() {
|
LazyDatabase _openConnection() {
|
||||||
return LazyDatabase(() async {
|
return LazyDatabase(() async {
|
||||||
final dbFolder = await getDatabasesPath();
|
final dbFolder = await getApplicationDocumentsDirectory();
|
||||||
final file = File(join(dbFolder, 'massive.db'));
|
final file = File(join(dbFolder.path, 'massive.db'));
|
||||||
print('file.path=${file.path}');
|
|
||||||
return VmDatabase(file, logStatements: true);
|
return VmDatabase(file, logStatements: true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ part of 'database.dart';
|
||||||
class Setting extends DataClass implements Insertable<Setting> {
|
class Setting extends DataClass implements Insertable<Setting> {
|
||||||
final bool alarm;
|
final bool alarm;
|
||||||
final bool vibrate;
|
final bool vibrate;
|
||||||
final String? sound;
|
final String sound;
|
||||||
final bool notify;
|
final bool notify;
|
||||||
final bool images;
|
final bool images;
|
||||||
final bool showUnit;
|
final bool showUnit;
|
||||||
|
@ -26,7 +26,7 @@ class Setting extends DataClass implements Insertable<Setting> {
|
||||||
Setting(
|
Setting(
|
||||||
{required this.alarm,
|
{required this.alarm,
|
||||||
required this.vibrate,
|
required this.vibrate,
|
||||||
this.sound,
|
required this.sound,
|
||||||
required this.notify,
|
required this.notify,
|
||||||
required this.images,
|
required this.images,
|
||||||
required this.showUnit,
|
required this.showUnit,
|
||||||
|
@ -48,7 +48,7 @@ class Setting extends DataClass implements Insertable<Setting> {
|
||||||
vibrate: const BoolType()
|
vibrate: const BoolType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}vibrate'])!,
|
.mapFromDatabaseResponse(data['${effectivePrefix}vibrate'])!,
|
||||||
sound: const StringType()
|
sound: const StringType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}sound']),
|
.mapFromDatabaseResponse(data['${effectivePrefix}sound'])!,
|
||||||
notify: const BoolType()
|
notify: const BoolType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}notify'])!,
|
.mapFromDatabaseResponse(data['${effectivePrefix}notify'])!,
|
||||||
images: const BoolType()
|
images: const BoolType()
|
||||||
|
@ -80,9 +80,7 @@ class Setting extends DataClass implements Insertable<Setting> {
|
||||||
final map = <String, Expression>{};
|
final map = <String, Expression>{};
|
||||||
map['alarm'] = Variable<bool>(alarm);
|
map['alarm'] = Variable<bool>(alarm);
|
||||||
map['vibrate'] = Variable<bool>(vibrate);
|
map['vibrate'] = Variable<bool>(vibrate);
|
||||||
if (!nullToAbsent || sound != null) {
|
map['sound'] = Variable<String>(sound);
|
||||||
map['sound'] = Variable<String?>(sound);
|
|
||||||
}
|
|
||||||
map['notify'] = Variable<bool>(notify);
|
map['notify'] = Variable<bool>(notify);
|
||||||
map['images'] = Variable<bool>(images);
|
map['images'] = Variable<bool>(images);
|
||||||
map['show_unit'] = Variable<bool>(showUnit);
|
map['show_unit'] = Variable<bool>(showUnit);
|
||||||
|
@ -106,8 +104,7 @@ class Setting extends DataClass implements Insertable<Setting> {
|
||||||
return SettingsCompanion(
|
return SettingsCompanion(
|
||||||
alarm: Value(alarm),
|
alarm: Value(alarm),
|
||||||
vibrate: Value(vibrate),
|
vibrate: Value(vibrate),
|
||||||
sound:
|
sound: Value(sound),
|
||||||
sound == null && nullToAbsent ? const Value.absent() : Value(sound),
|
|
||||||
notify: Value(notify),
|
notify: Value(notify),
|
||||||
images: Value(images),
|
images: Value(images),
|
||||||
showUnit: Value(showUnit),
|
showUnit: Value(showUnit),
|
||||||
|
@ -133,7 +130,7 @@ class Setting extends DataClass implements Insertable<Setting> {
|
||||||
return Setting(
|
return Setting(
|
||||||
alarm: serializer.fromJson<bool>(json['alarm']),
|
alarm: serializer.fromJson<bool>(json['alarm']),
|
||||||
vibrate: serializer.fromJson<bool>(json['vibrate']),
|
vibrate: serializer.fromJson<bool>(json['vibrate']),
|
||||||
sound: serializer.fromJson<String?>(json['sound']),
|
sound: serializer.fromJson<String>(json['sound']),
|
||||||
notify: serializer.fromJson<bool>(json['notify']),
|
notify: serializer.fromJson<bool>(json['notify']),
|
||||||
images: serializer.fromJson<bool>(json['images']),
|
images: serializer.fromJson<bool>(json['images']),
|
||||||
showUnit: serializer.fromJson<bool>(json['showUnit']),
|
showUnit: serializer.fromJson<bool>(json['showUnit']),
|
||||||
|
@ -154,7 +151,7 @@ class Setting extends DataClass implements Insertable<Setting> {
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{
|
||||||
'alarm': serializer.toJson<bool>(alarm),
|
'alarm': serializer.toJson<bool>(alarm),
|
||||||
'vibrate': serializer.toJson<bool>(vibrate),
|
'vibrate': serializer.toJson<bool>(vibrate),
|
||||||
'sound': serializer.toJson<String?>(sound),
|
'sound': serializer.toJson<String>(sound),
|
||||||
'notify': serializer.toJson<bool>(notify),
|
'notify': serializer.toJson<bool>(notify),
|
||||||
'images': serializer.toJson<bool>(images),
|
'images': serializer.toJson<bool>(images),
|
||||||
'showUnit': serializer.toJson<bool>(showUnit),
|
'showUnit': serializer.toJson<bool>(showUnit),
|
||||||
|
@ -266,7 +263,7 @@ class Setting extends DataClass implements Insertable<Setting> {
|
||||||
class SettingsCompanion extends UpdateCompanion<Setting> {
|
class SettingsCompanion extends UpdateCompanion<Setting> {
|
||||||
final Value<bool> alarm;
|
final Value<bool> alarm;
|
||||||
final Value<bool> vibrate;
|
final Value<bool> vibrate;
|
||||||
final Value<String?> sound;
|
final Value<String> sound;
|
||||||
final Value<bool> notify;
|
final Value<bool> notify;
|
||||||
final Value<bool> images;
|
final Value<bool> images;
|
||||||
final Value<bool> showUnit;
|
final Value<bool> showUnit;
|
||||||
|
@ -299,7 +296,7 @@ class SettingsCompanion extends UpdateCompanion<Setting> {
|
||||||
SettingsCompanion.insert({
|
SettingsCompanion.insert({
|
||||||
required bool alarm,
|
required bool alarm,
|
||||||
required bool vibrate,
|
required bool vibrate,
|
||||||
this.sound = const Value.absent(),
|
required String sound,
|
||||||
required bool notify,
|
required bool notify,
|
||||||
required bool images,
|
required bool images,
|
||||||
required bool showUnit,
|
required bool showUnit,
|
||||||
|
@ -314,6 +311,7 @@ class SettingsCompanion extends UpdateCompanion<Setting> {
|
||||||
required bool backup,
|
required bool backup,
|
||||||
}) : alarm = Value(alarm),
|
}) : alarm = Value(alarm),
|
||||||
vibrate = Value(vibrate),
|
vibrate = Value(vibrate),
|
||||||
|
sound = Value(sound),
|
||||||
notify = Value(notify),
|
notify = Value(notify),
|
||||||
images = Value(images),
|
images = Value(images),
|
||||||
showUnit = Value(showUnit),
|
showUnit = Value(showUnit),
|
||||||
|
@ -327,7 +325,7 @@ class SettingsCompanion extends UpdateCompanion<Setting> {
|
||||||
static Insertable<Setting> custom({
|
static Insertable<Setting> custom({
|
||||||
Expression<bool>? alarm,
|
Expression<bool>? alarm,
|
||||||
Expression<bool>? vibrate,
|
Expression<bool>? vibrate,
|
||||||
Expression<String?>? sound,
|
Expression<String>? sound,
|
||||||
Expression<bool>? notify,
|
Expression<bool>? notify,
|
||||||
Expression<bool>? images,
|
Expression<bool>? images,
|
||||||
Expression<bool>? showUnit,
|
Expression<bool>? showUnit,
|
||||||
|
@ -363,7 +361,7 @@ class SettingsCompanion extends UpdateCompanion<Setting> {
|
||||||
SettingsCompanion copyWith(
|
SettingsCompanion copyWith(
|
||||||
{Value<bool>? alarm,
|
{Value<bool>? alarm,
|
||||||
Value<bool>? vibrate,
|
Value<bool>? vibrate,
|
||||||
Value<String?>? sound,
|
Value<String>? sound,
|
||||||
Value<bool>? notify,
|
Value<bool>? notify,
|
||||||
Value<bool>? images,
|
Value<bool>? images,
|
||||||
Value<bool>? showUnit,
|
Value<bool>? showUnit,
|
||||||
|
@ -405,7 +403,7 @@ class SettingsCompanion extends UpdateCompanion<Setting> {
|
||||||
map['vibrate'] = Variable<bool>(vibrate.value);
|
map['vibrate'] = Variable<bool>(vibrate.value);
|
||||||
}
|
}
|
||||||
if (sound.present) {
|
if (sound.present) {
|
||||||
map['sound'] = Variable<String?>(sound.value);
|
map['sound'] = Variable<String>(sound.value);
|
||||||
}
|
}
|
||||||
if (notify.present) {
|
if (notify.present) {
|
||||||
map['notify'] = Variable<bool>(notify.value);
|
map['notify'] = Variable<bool>(notify.value);
|
||||||
|
@ -491,8 +489,8 @@ class $SettingsTable extends Settings with TableInfo<$SettingsTable, Setting> {
|
||||||
final VerificationMeta _soundMeta = const VerificationMeta('sound');
|
final VerificationMeta _soundMeta = const VerificationMeta('sound');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<String?> sound = GeneratedColumn<String?>(
|
late final GeneratedColumn<String?> sound = GeneratedColumn<String?>(
|
||||||
'sound', aliasedName, true,
|
'sound', aliasedName, false,
|
||||||
type: const StringType(), requiredDuringInsert: false);
|
type: const StringType(), requiredDuringInsert: true);
|
||||||
final VerificationMeta _notifyMeta = const VerificationMeta('notify');
|
final VerificationMeta _notifyMeta = const VerificationMeta('notify');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<bool?> notify = GeneratedColumn<bool?>(
|
late final GeneratedColumn<bool?> notify = GeneratedColumn<bool?>(
|
||||||
|
@ -611,6 +609,8 @@ class $SettingsTable extends Settings with TableInfo<$SettingsTable, Setting> {
|
||||||
if (data.containsKey('sound')) {
|
if (data.containsKey('sound')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_soundMeta, sound.isAcceptableOrUnknown(data['sound']!, _soundMeta));
|
_soundMeta, sound.isAcceptableOrUnknown(data['sound']!, _soundMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_soundMeta);
|
||||||
}
|
}
|
||||||
if (data.containsKey('notify')) {
|
if (data.containsKey('notify')) {
|
||||||
context.handle(_notifyMeta,
|
context.handle(_notifyMeta,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/material.dart' as material;
|
import 'package:flutter/material.dart' as material;
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:fmassive/database.dart';
|
import 'package:fmassive/database.dart';
|
||||||
import 'package:fmassive/main.dart';
|
import 'package:fmassive/main.dart';
|
||||||
import 'package:moor_flutter/moor_flutter.dart';
|
import 'package:moor_flutter/moor_flutter.dart';
|
||||||
|
@ -19,8 +18,6 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
final TextEditingController _repsController = TextEditingController();
|
final TextEditingController _repsController = TextEditingController();
|
||||||
final TextEditingController _weightController = TextEditingController();
|
final TextEditingController _weightController = TextEditingController();
|
||||||
late GymSetsCompanion gymSet;
|
late GymSetsCompanion gymSet;
|
||||||
final nameNode = FocusNode();
|
|
||||||
final repsNode = FocusNode();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -29,17 +26,6 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
_nameController.text = gymSet.name.value;
|
_nameController.text = gymSet.name.value;
|
||||||
_repsController.text = gymSet.reps.value.toString();
|
_repsController.text = gymSet.reps.value.toString();
|
||||||
_weightController.text = gymSet.weight.value.toString();
|
_weightController.text = gymSet.weight.value.toString();
|
||||||
if (gymSet.id.present)
|
|
||||||
repsNode.requestFocus();
|
|
||||||
else
|
|
||||||
nameNode.requestFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
dispose() {
|
|
||||||
nameNode.dispose();
|
|
||||||
repsNode.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -63,12 +49,7 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
children: [
|
children: [
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _nameController,
|
controller: _nameController,
|
||||||
focusNode: nameNode,
|
|
||||||
decoration: const InputDecoration(labelText: 'Name'),
|
decoration: const InputDecoration(labelText: 'Name'),
|
||||||
onTap: () {
|
|
||||||
_nameController.selection = TextSelection(
|
|
||||||
baseOffset: 0, extentOffset: _nameController.text.length);
|
|
||||||
},
|
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
gymSet = gymSet.copyWith(name: Value(value));
|
gymSet = gymSet.copyWith(name: Value(value));
|
||||||
|
@ -77,11 +58,6 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
),
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _repsController,
|
controller: _repsController,
|
||||||
focusNode: repsNode,
|
|
||||||
onTap: () {
|
|
||||||
_repsController.selection = TextSelection(
|
|
||||||
baseOffset: 0, extentOffset: _repsController.text.length);
|
|
||||||
},
|
|
||||||
decoration: const InputDecoration(labelText: 'Reps'),
|
decoration: const InputDecoration(labelText: 'Reps'),
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
@ -95,10 +71,6 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
controller: _weightController,
|
controller: _weightController,
|
||||||
decoration: const InputDecoration(labelText: 'Weight (kg)'),
|
decoration: const InputDecoration(labelText: 'Weight (kg)'),
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
onTap: () {
|
|
||||||
_weightController.selection = TextSelection(
|
|
||||||
baseOffset: 0, extentOffset: _weightController.text.length);
|
|
||||||
},
|
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
gymSet =
|
gymSet =
|
||||||
|
@ -113,11 +85,8 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (gymSet.id.present)
|
if (gymSet.id.present)
|
||||||
await db.update(db.gymSets).write(gymSet);
|
await db.update(db.gymSets).write(gymSet);
|
||||||
else {
|
else
|
||||||
await db.into(db.gymSets).insert(gymSet);
|
await db.into(db.gymSets).insert(gymSet);
|
||||||
const platform = MethodChannel('com.massive/android');
|
|
||||||
platform.invokeMethod('timer', [3000]);
|
|
||||||
}
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,7 +33,6 @@ class RootPage extends State<HomePage> {
|
||||||
|
|
||||||
void toggleSearch() {
|
void toggleSearch() {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (showSearch) search = '';
|
|
||||||
showSearch = !showSearch;
|
showSearch = !showSearch;
|
||||||
});
|
});
|
||||||
focusNode.requestFocus();
|
focusNode.requestFocus();
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:moor/moor.dart';
|
||||||
Setting defaultSettings = Setting(
|
Setting defaultSettings = Setting(
|
||||||
alarm: true,
|
alarm: true,
|
||||||
vibrate: true,
|
vibrate: true,
|
||||||
sound: null,
|
sound: 'default.mp3',
|
||||||
notify: true,
|
notify: true,
|
||||||
images: true,
|
images: true,
|
||||||
showUnit: true,
|
showUnit: true,
|
||||||
|
@ -22,7 +22,7 @@ Setting defaultSettings = Setting(
|
||||||
class Settings extends Table {
|
class Settings extends Table {
|
||||||
BoolColumn get alarm => boolean()();
|
BoolColumn get alarm => boolean()();
|
||||||
BoolColumn get vibrate => boolean()();
|
BoolColumn get vibrate => boolean()();
|
||||||
TextColumn get sound => text().nullable()();
|
TextColumn get sound => text()();
|
||||||
BoolColumn get notify => boolean()();
|
BoolColumn get notify => boolean()();
|
||||||
BoolColumn get images => boolean()();
|
BoolColumn get images => boolean()();
|
||||||
BoolColumn get showUnit => boolean()();
|
BoolColumn get showUnit => boolean()();
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/material.dart' as material;
|
import 'package:flutter/material.dart' as material;
|
||||||
import 'package:fmassive/database.dart';
|
import 'package:fmassive/database.dart';
|
||||||
import 'package:fmassive/main.dart';
|
import 'package:fmassive/main.dart';
|
||||||
|
import 'package:fmassive/settings.dart';
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
|
|
||||||
class SettingsPage extends StatelessWidget {
|
class SettingsPage extends StatelessWidget {
|
||||||
|
@ -29,9 +30,15 @@ class _SettingsPageState extends State<_SettingsPage> {
|
||||||
|
|
||||||
final TextEditingController searchController = TextEditingController();
|
final TextEditingController searchController = TextEditingController();
|
||||||
|
|
||||||
|
void reset() async {
|
||||||
|
var data = await db.select(db.settings).get();
|
||||||
|
if (data.isEmpty) await db.into(db.settings).insert(defaultSettings);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
reset();
|
||||||
stream = db.select(db.settings).watchSingle();
|
stream = db.select(db.settings).watchSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user