diff --git a/.gitignore b/.gitignore index 0de4d0a16..a259a6db2 100644 --- a/.gitignore +++ b/.gitignore @@ -56,5 +56,7 @@ app.*.map.json /firebase.json /.fvm /.tmp +/.worktrees/ /caches -/.fvmrc \ No newline at end of file +/.fvmrc +/artifacts/ diff --git a/android/app/build.gradle b/android/app/build.gradle index 3da777f22..2ccc998f8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,3 +1,10 @@ +plugins { + id "com.android.application" + id "org.jetbrains.kotlin.android" + id "dev.flutter.flutter-gradle-plugin" + id "com.google.gms.google-services" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,11 +13,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new Exception("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '4' @@ -21,11 +23,6 @@ if (flutterVersionName == null) { flutterVersionName = '0.2.1' } -apply plugin: 'com.android.application' -apply plugin: 'com.google.gms.google-services' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { @@ -33,7 +30,8 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 34 + namespace "com.ccextractor.ultimate_alarm_clock" + compileSdk 36 ndkVersion flutter.ndkVersion defaultConfig { @@ -41,8 +39,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. applicationId "com.ccextractor.ultimate_alarm_clock" - minSdkVersion 24 - targetSdkVersion 34 // Updated to latest targetSdkVersion + minSdk 24 + targetSdk 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true @@ -51,12 +49,12 @@ android { compileOptions { - sourceCompatibility JavaVersion.VERSION_17 // Updated to Java 17 + sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = '17' // Updated to Java 17 + jvmTarget = '17' } sourceSets { @@ -93,12 +91,10 @@ flutter { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-stdlib:1.7.10" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10" - implementation platform('com.google.firebase:firebase-bom:32.0.0') // Updated Firebase BOM to latest + implementation platform('com.google.firebase:firebase-bom:32.0.0') implementation 'com.google.firebase:protolite-well-known-types:18.0.0' implementation("com.android.volley:volley:1.2.1") implementation("com.google.code.gson:gson:2.10.1") implementation("androidx.multidex:multidex:2.0.1") -} \ No newline at end of file + testImplementation "junit:junit:4.13.2" +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 64507121e..a1a765a1d 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> @@ -45,8 +44,7 @@ android:name="${applicationName}" android:allowBackup="true" android:icon="@mipmap/launcher_icon" - android:label="Ultimate Alarm Clock" - tools:replace="android:label"> + android:label="Ultimate Alarm Clock"> + + - \ No newline at end of file + diff --git a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/AlarmScheduleContract.kt b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/AlarmScheduleContract.kt new file mode 100644 index 000000000..614f7eedb --- /dev/null +++ b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/AlarmScheduleContract.kt @@ -0,0 +1,371 @@ +package com.ccextractor.ultimate_alarm_clock + +import android.annotation.SuppressLint +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.UserManager +import android.util.Log +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.ZoneId +import java.time.format.DateTimeFormatter +import java.time.format.DateTimeParseException + +data class ScheduledAlarmPayload( + val triggerAtMs: Long, + val activityMonitor: Int, + val locationMonitor: Int, + val location: String, + val isWeather: Int, + val weatherTypes: String +) + +object AlarmScheduleStore { + private const val PREFS_NAME = "ultimate_alarm_clock_schedule" + private const val KEY_TRIGGER_AT_MS = "trigger_at_ms" + private const val KEY_ACTIVITY_MONITOR = "activity_monitor" + private const val KEY_LOCATION_MONITOR = "location_monitor" + private const val KEY_LOCATION = "location" + private const val KEY_IS_WEATHER = "is_weather" + private const val KEY_WEATHER_TYPES = "weather_types" + + private fun deviceProtectedContext(context: Context): Context { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + context.createDeviceProtectedStorageContext() + } else { + context + } + } + + fun canAccessCredentialEncryptedStorage(context: Context): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + return true + } + + val userManager = context.getSystemService(UserManager::class.java) + return userManager?.isUserUnlocked != false + } + + private fun writePreferences(context: Context, payload: ScheduledAlarmPayload) { + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .edit() + .putLong(KEY_TRIGGER_AT_MS, payload.triggerAtMs) + .putInt(KEY_ACTIVITY_MONITOR, payload.activityMonitor) + .putInt(KEY_LOCATION_MONITOR, payload.locationMonitor) + .putString(KEY_LOCATION, payload.location) + .putInt(KEY_IS_WEATHER, payload.isWeather) + .putString(KEY_WEATHER_TYPES, payload.weatherTypes) + .apply() + } + + private fun readPreferences(context: Context): ScheduledAlarmPayload? { + val preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + if (!preferences.contains(KEY_TRIGGER_AT_MS)) { + return null + } + + return ScheduledAlarmPayload( + triggerAtMs = preferences.getLong(KEY_TRIGGER_AT_MS, -1L), + activityMonitor = preferences.getInt(KEY_ACTIVITY_MONITOR, 0), + locationMonitor = preferences.getInt(KEY_LOCATION_MONITOR, 0), + location = preferences.getString(KEY_LOCATION, "") ?: "", + isWeather = preferences.getInt(KEY_IS_WEATHER, 0), + weatherTypes = preferences.getString(KEY_WEATHER_TYPES, "[]") ?: "[]" + ) + } + + fun save(context: Context, payload: ScheduledAlarmPayload) { + val protectedContext = deviceProtectedContext(context) + writePreferences(protectedContext, payload) + if (protectedContext !== context && canAccessCredentialEncryptedStorage(context)) { + writePreferences(context, payload) + } + } + + fun load(context: Context): ScheduledAlarmPayload? { + val protectedContext = deviceProtectedContext(context) + val protectedPayload = readPreferences(protectedContext) + if (protectedPayload != null) { + return protectedPayload + } + + val legacyPayload = if ( + protectedContext !== context && + canAccessCredentialEncryptedStorage(context) + ) { + readPreferences(context) + } else { + null + } + + if (legacyPayload != null) { + writePreferences(protectedContext, legacyPayload) + } + + return legacyPayload + } + + fun clear(context: Context) { + val protectedContext = deviceProtectedContext(context) + protectedContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .edit() + .clear() + .apply() + if (protectedContext !== context && canAccessCredentialEncryptedStorage(context)) { + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .edit() + .clear() + .apply() + } + } +} + +object BootRestorePlanner { + fun chooseAlarmToRestore( + persistedAlarm: ScheduledAlarmPayload?, + localAlarm: ScheduledAlarmPayload?, + nowMs: Long, + allowLocalFallback: Boolean, + ): ScheduledAlarmPayload? { + val validLocal = if (allowLocalFallback) { + localAlarm?.takeIf { it.triggerAtMs > nowMs } + } else { + null + } + if (validLocal != null) { + return validLocal + } + + val validPersisted = persistedAlarm?.takeIf { it.triggerAtMs > nowMs } + if (validPersisted != null) { + return validPersisted + } + return null + } +} + +object LocalAlarmScheduleResolver { + private val timeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("H:mm") + + fun nextTriggerAtMs( + alarm: AlarmModel, + nowMs: Long, + zoneId: ZoneId = ZoneId.systemDefault(), + ): Long? { + val referenceTime = Instant.ofEpochMilli(nowMs).atZone(zoneId).toLocalDateTime() + val alarmTime = parseTime(alarm.alarmTime) ?: return null + + if (alarm.ringOn == 1) { + val alarmDate = parseDate(alarm.alarmDate) ?: return null + return toEpochMillis(LocalDateTime.of(alarmDate, alarmTime), zoneId) + ?.takeIf { it > nowMs } + } + + if (alarm.days.any { it == '1' }) { + for (offset in 0..7) { + val candidateDate = referenceTime.toLocalDate().plusDays(offset.toLong()) + val candidate = LocalDateTime.of(candidateDate, alarmTime) + val dayIndex = candidate.dayOfWeek.value % 7 + if (alarm.days.getOrNull(dayIndex) == '1' && candidate.isAfter(referenceTime)) { + return toEpochMillis(candidate, zoneId) + } + } + + return null + } + + val today = LocalDateTime.of(referenceTime.toLocalDate(), alarmTime) + val nextCandidate = if (today.isAfter(referenceTime)) { + today + } else { + today.plusDays(1) + } + return toEpochMillis(nextCandidate, zoneId) + } + + private fun parseTime(rawTime: String): LocalTime? { + return try { + LocalTime.parse(rawTime, timeFormatter) + } catch (_: DateTimeParseException) { + null + } + } + + private fun parseDate(rawDate: String): LocalDate? { + return try { + LocalDate.parse(rawDate.trim()) + } catch (_: DateTimeParseException) { + null + } + } + + private fun toEpochMillis(dateTime: LocalDateTime, zoneId: ZoneId): Long? { + return try { + dateTime.atZone(zoneId).toInstant().toEpochMilli() + } catch (_: DateTimeParseException) { + null + } + } +} + +object AlarmScheduler { + private const val ALARM_REQUEST_CODE = 0 + private const val LEGACY_BOOT_ALARM_REQUEST_CODE = 1 + private const val ACTIVITY_REQUEST_CODE = 4 + private const val LOCATION_REQUEST_CODE = 5 + private const val WEATHER_REQUEST_CODE = 6 + + @SuppressLint("ScheduleExactAlarm") + fun schedule( + context: Context, + payload: ScheduledAlarmPayload, + allowCredentialEncryptedAccess: Boolean = AlarmScheduleStore.canAccessCredentialEncryptedStorage(context), + ) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val now = System.currentTimeMillis() + val triggerAtMs = payload.triggerAtMs + + if (triggerAtMs <= now) { + Log.d("AlarmScheduler", "Skipping stale alarm payload at $triggerAtMs") + clear(context) + return + } + + val intent = Intent(context, AlarmReceiver::class.java) + val pendingIntent = PendingIntent.getBroadcast( + context, + ALARM_REQUEST_CODE, + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + val activityCheckIntent = Intent(context, ScreenMonitorService::class.java) + val pendingActivityCheckIntent = PendingIntent.getService( + context, + ACTIVITY_REQUEST_CODE, + activityCheckIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + + val tenMinutesInMilliseconds = 600000L + val preTriggerTime = maxOf(now, triggerAtMs - tenMinutesInMilliseconds) + + if (!allowCredentialEncryptedAccess) { + val alarmClockInfo = AlarmManager.AlarmClockInfo(triggerAtMs, pendingIntent) + alarmManager.setAlarmClock(alarmClockInfo, pendingIntent) + return + } + + if (payload.activityMonitor == 1) { + val alarmClockInfo = AlarmManager.AlarmClockInfo(preTriggerTime, pendingIntent) + alarmManager.setAlarmClock(alarmClockInfo, pendingActivityCheckIntent) + } else { + val sharedPreferences = + context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) + sharedPreferences.edit() + .putLong("flutter.is_screen_off", 0L) + .putLong("flutter.is_screen_on", 0L) + .apply() + } + + if (payload.locationMonitor == 1) { + val sharedPreferences = + context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) + sharedPreferences.edit() + .putString("flutter.set_location", payload.location) + .putInt("flutter.is_location_on", 1) + .apply() + Log.d("location", payload.location) + + val locationAlarmIntent = Intent(context, LocationFetcherService::class.java) + val pendingLocationAlarmIntent = PendingIntent.getService( + context, + LOCATION_REQUEST_CODE, + locationAlarmIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + val alarmClockInfo = AlarmManager.AlarmClockInfo(maxOf(now, triggerAtMs - 10000), pendingIntent) + alarmManager.setAlarmClock(alarmClockInfo, pendingLocationAlarmIntent) + } else if (payload.isWeather == 1) { + val sharedPreferences = + context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) + val weatherConditions = getWeatherConditions(payload.weatherTypes) + sharedPreferences.edit() + .putString("flutter.weatherTypes", weatherConditions) + .apply() + Log.d("we", weatherConditions) + + val weatherAlarmIntent = Intent(context, WeatherFetcherService::class.java) + val pendingWeatherAlarmIntent = PendingIntent.getService( + context, + WEATHER_REQUEST_CODE, + weatherAlarmIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + val alarmClockInfo = AlarmManager.AlarmClockInfo(maxOf(now, triggerAtMs - 10000), pendingIntent) + alarmManager.setAlarmClock(alarmClockInfo, pendingWeatherAlarmIntent) + } else { + val alarmClockInfo = AlarmManager.AlarmClockInfo(triggerAtMs, pendingIntent) + alarmManager.setAlarmClock(alarmClockInfo, pendingIntent) + } + } + + fun clear(context: Context) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + + val alarmIntent = Intent(context, AlarmReceiver::class.java) + val pendingIntent = PendingIntent.getBroadcast( + context, + ALARM_REQUEST_CODE, + alarmIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + alarmManager.cancel(pendingIntent) + pendingIntent.cancel() + + val legacyBootPendingIntent = PendingIntent.getBroadcast( + context, + LEGACY_BOOT_ALARM_REQUEST_CODE, + alarmIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + alarmManager.cancel(legacyBootPendingIntent) + legacyBootPendingIntent.cancel() + + val activityIntent = Intent(context, ScreenMonitorService::class.java) + val pendingActivityIntent = PendingIntent.getService( + context, + ACTIVITY_REQUEST_CODE, + activityIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + alarmManager.cancel(pendingActivityIntent) + pendingActivityIntent.cancel() + + val locationIntent = Intent(context, LocationFetcherService::class.java) + val pendingLocationIntent = PendingIntent.getService( + context, + LOCATION_REQUEST_CODE, + locationIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + alarmManager.cancel(pendingLocationIntent) + pendingLocationIntent.cancel() + + val weatherIntent = Intent(context, WeatherFetcherService::class.java) + val pendingWeatherIntent = PendingIntent.getService( + context, + WEATHER_REQUEST_CODE, + weatherIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + alarmManager.cancel(pendingWeatherIntent) + pendingWeatherIntent.cancel() + + AlarmScheduleStore.clear(context) + } +} diff --git a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/BootReceiver.kt b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/BootReceiver.kt index e7d1ffcba..f2c310744 100644 --- a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/BootReceiver.kt +++ b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/BootReceiver.kt @@ -1,116 +1,138 @@ package com.ccextractor.ultimate_alarm_clock -import android.annotation.SuppressLint -import android.app.AlarmManager -import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.os.SystemClock +import android.app.PendingIntent import android.app.NotificationChannel import android.app.NotificationManager import android.os.Build -import android.os.CountDownTimer +import android.util.Log import androidx.core.app.NotificationCompat import com.ccextractor.ultimate_alarm_clock.getLatestTimer class BootReceiver : BroadcastReceiver() { + companion object { + private const val TAG = "BootReceiver" + } override fun onReceive(context: Context, intent: Intent) { + val action = intent.action ?: return + if ( + action != Intent.ACTION_BOOT_COMPLETED && + action != Intent.ACTION_USER_UNLOCKED && + action != Intent.ACTION_LOCKED_BOOT_COMPLETED + ) { + return + } - if (intent.action == Intent.ACTION_BOOT_COMPLETED) { - val sharedPreferences = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) - val profile = sharedPreferences.getString("flutter.profile", "Default") - - val dbHelper = DatabaseHelper(context) - val logdbHelper = LogDatabaseHelper(context) - val db = dbHelper.readableDatabase - val ringTime = getLatestAlarm(db, true, profile?:"Default", context) - db.close() - if (ringTime != null) { - scheduleAlarm(ringTime["interval"]!! as Long, context, ringTime["isActivity"]!!) - } - - val timerdbhelper = TimerDatabaseHelper(context) - val timerdb = timerdbhelper.readableDatabase - val time = getLatestTimer(timerdb) - timerdb.close() - var notificationManager = - context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - val commonTimer = CommonTimerManager.getCommonTimer(object : TimerListener { - override fun onTick(millisUntilFinished: Long) { - println(millisUntilFinished) - showTimerNotification(millisUntilFinished, "Timer", context) - - } - - override fun onFinish() { - notificationManager.cancel(1) - } - }) - createNotificationChannel(context) - + Log.i(TAG, "Handling action=$action") + val allowLocalFallback = action != Intent.ACTION_LOCKED_BOOT_COMPLETED + restoreAlarms(context, allowLocalFallback) + if (action != Intent.ACTION_LOCKED_BOOT_COMPLETED) { + restoreTimers(context) + } + } + private fun restoreAlarms(context: Context, allowLocalFallback: Boolean) { + val now = System.currentTimeMillis() + val persistedAlarm = AlarmScheduleStore.load(context) + val localAlarm = if (allowLocalFallback) restoreAlarmFromLocalState(context) else null - if (time != null) { + val reconciledAlarm = BootRestorePlanner.chooseAlarmToRestore( + persistedAlarm = persistedAlarm, + localAlarm = localAlarm, + nowMs = now, + allowLocalFallback = allowLocalFallback + ) + Log.i( + TAG, + "restoreAlarms allowLocalFallback=$allowLocalFallback persisted=${persistedAlarm?.triggerAtMs} local=${localAlarm?.triggerAtMs} reconciled=${reconciledAlarm?.triggerAtMs}" + ) + if (reconciledAlarm != null) { + AlarmScheduleStore.save(context, reconciledAlarm) + AlarmScheduler.schedule( + context, + reconciledAlarm, + allowCredentialEncryptedAccess = AlarmScheduleStore.canAccessCredentialEncryptedStorage(context) + ) + Log.i(TAG, "Scheduled restored alarm at ${reconciledAlarm.triggerAtMs}") + } else { + AlarmScheduleStore.clear(context) + Log.i(TAG, "No valid alarm found to restore") + } + } - // Start or stop the timer based on your requirements - commonTimer.startTimer(time.second) + private fun restoreTimers(context: Context) { + val timerdbhelper = TimerDatabaseHelper(context) + val timerdb = timerdbhelper.readableDatabase + val time = getLatestTimer(timerdb) + timerdb.close() + val notificationManager = + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val commonTimer = CommonTimerManager.getCommonTimer(object : TimerListener { + override fun onTick(millisUntilFinished: Long) { + println(millisUntilFinished) + showTimerNotification(millisUntilFinished, "Timer", context) } + override fun onFinish() { + notificationManager.cancel(1) + } + }) + createNotificationChannel(context) + if (time != null) { + commonTimer.startTimer(time.second) + Log.i(TAG, "Restored timer for ${time.second} seconds") + } + else { + Log.i(TAG, "No timer found to restore") } } - @SuppressLint("ScheduleExactAlarm") - fun scheduleAlarm(milliSeconds: Long, context: Context, activityMonitor: Any) { - val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager - val intent = Intent(context, AlarmReceiver::class.java) - val pendingIntent = PendingIntent.getBroadcast( - context, - 1, - intent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + private fun restoreAlarmFromLocalState(context: Context): ScheduledAlarmPayload? { + val sharedPreferences = + context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) + val profile = sharedPreferences.getString("flutter.profile", "Default") + val dbHelper = DatabaseHelper(context) + val db = dbHelper.readableDatabase + val cursor = db.rawQuery( + """ + SELECT * FROM alarms + WHERE isEnabled = 1 + AND (profile = ? OR ringOn = 1) + """.trimIndent(), + arrayOf(profile ?: "Default") ) - val activityCheckIntent = Intent(context, ScreenMonitorService::class.java) - val pendingActivityCheckIntent = PendingIntent.getService( - context, - 4, - activityCheckIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - ) - // Schedule the alarm - val tenMinutesInMilliseconds = 600000L - val preTriggerTime = - System.currentTimeMillis() + (milliSeconds - tenMinutesInMilliseconds) - - // Schedule the alarm - val triggerTime = System.currentTimeMillis() + milliSeconds - - if (activityMonitor == 1) { - val alarmClockInfo = AlarmManager.AlarmClockInfo(preTriggerTime, pendingIntent) - alarmManager.setAlarmClock( - alarmClockInfo, - pendingActivityCheckIntent - ) - } else { - val sharedPreferences = - context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) - val editor = sharedPreferences.edit() - editor.putLong("flutter.is_screen_off", 0L) - editor.apply() - editor.putLong("flutter.is_screen_on", 0L) - editor.apply() - } - val clockInfo = AlarmManager.AlarmClockInfo(triggerTime, pendingIntent) - alarmManager.setAlarmClock(clockInfo, pendingIntent) + return try { + var bestPayload: ScheduledAlarmPayload? = null + val now = System.currentTimeMillis() + while (cursor.moveToNext()) { + val alarm = AlarmModel.fromCursor(cursor) + val triggerAtMs = LocalAlarmScheduleResolver.nextTriggerAtMs(alarm, now) ?: continue + val candidate = ScheduledAlarmPayload( + triggerAtMs = triggerAtMs, + activityMonitor = alarm.activityMonitor, + locationMonitor = alarm.isLocationEnabled, + location = alarm.location, + isWeather = alarm.isWeatherEnabled, + weatherTypes = alarm.weatherTypes + ) + if (bestPayload == null || candidate.triggerAtMs < bestPayload.triggerAtMs) { + bestPayload = candidate + } + } + bestPayload + } finally { + cursor.close() + db.close() + } } - - private fun createNotificationChannel(context: Context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -156,4 +178,4 @@ class BootReceiver : BroadcastReceiver() { String.format("%02d:%02d", minutes, seconds) } } -} \ No newline at end of file +} diff --git a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt index f97f97f76..589682adb 100644 --- a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt +++ b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt @@ -1,10 +1,7 @@ package com.ccextractor.ultimate_alarm_clock -import android.annotation.SuppressLint import android.app.ActivityManager -import android.app.AlarmManager import android.app.NotificationManager -import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.IntentFilter @@ -17,13 +14,13 @@ import android.media.RingtoneManager import android.net.Uri import android.os.Build import android.os.Bundle -import android.os.SystemClock import android.provider.Settings import android.util.Log import android.view.WindowManager import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel @@ -135,28 +132,13 @@ class MainActivity : FlutterActivity() { } methodChannel1.setMethodCallHandler { call, result -> if (call.method == "scheduleAlarm") { - println("FLUTTER CALLED SCHEDULE") - val dbHelper = DatabaseHelper(context) - val db = dbHelper.readableDatabase - val sharedPreferences = - context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) - val profile = sharedPreferences.getString("flutter.profile", "Default") - val ringTime = getLatestAlarm(db, true, profile ?: "Default", context) - Log.d("yay yay", "yay ${ringTime ?: "null"}") - if (ringTime != null) { - android.util.Log.d("yay", "yay ${ringTime["interval"]}") - Log.d("yay", "yay ${ringTime["isLocation"]}") - scheduleAlarm( - ringTime["interval"]!! as Long, - ringTime["isActivity"]!! as Int, - ringTime["isLocation"]!! as Int, - ringTime["location"]!! as String, - ringTime["isWeather"]!! as Int, - ringTime["weatherTypes"]!! as String + if (!scheduleAlarmFromPayload(call)) { + result.error( + "INVALID_ARGUMENT", + "scheduleAlarm requires a payload generated by Flutter", + null ) - } else { - println("FLUTTER CALLED CANCEL ALARMS") - cancelAllScheduledAlarms() + return@setMethodCallHandler } result.success(null) } else if (call.method == "cancelAllScheduledAlarms") { @@ -181,6 +163,29 @@ class MainActivity : FlutterActivity() { } } + private fun scheduleAlarmFromPayload(call: MethodCall): Boolean { + val triggerAtMs = + call.argument("triggerAtMs")?.toLong() + ?: return false + val activityMonitor = call.argument("activityMonitor") ?: return false + val locationMonitor = call.argument("locationMonitor") ?: 0 + val location = call.argument("location") ?: "" + val isWeather = call.argument("isWeather") ?: 0 + val weatherTypes = call.argument("weatherTypes") ?: "[]" + + val payload = ScheduledAlarmPayload( + triggerAtMs, + activityMonitor, + locationMonitor, + location, + isWeather, + weatherTypes + ) + AlarmScheduleStore.save(this, payload) + AlarmScheduler.schedule(this, payload) + return true + } + fun bringAppToForeground(context: Context) { val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager? @@ -199,123 +204,8 @@ class MainActivity : FlutterActivity() { } - @SuppressLint("ScheduleExactAlarm") - private fun scheduleAlarm( - milliSeconds: Long, - activityMonitor: Int, - locationMonitor: Int, - setLocation: String, - isWeather: Int, - weatherTypes: String - ) { - - val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager - val intent = Intent(this, AlarmReceiver::class.java) - val pendingIntent = PendingIntent.getBroadcast( - this, - 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - ) - val activityCheckIntent = Intent(this, ScreenMonitorService::class.java) - val pendingActivityCheckIntent = PendingIntent.getService( - this, - 4, - activityCheckIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - ) - // Schedule the alarm - val tenMinutesInMilliseconds = 600000L - val preTriggerTime = - System.currentTimeMillis() + (milliSeconds - tenMinutesInMilliseconds) - val triggerTime = System.currentTimeMillis() + milliSeconds - if (activityMonitor == 1) { - val alarmClockInfo = AlarmManager.AlarmClockInfo(preTriggerTime, pendingIntent) - alarmManager.setAlarmClock( - alarmClockInfo, - pendingActivityCheckIntent - ) - } else { - val sharedPreferences = - getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) - val editor = sharedPreferences.edit() - editor.putLong("flutter.is_screen_off", 0L) - editor.apply() - editor.putLong("flutter.is_screen_on", 0L) - editor.apply() - } - if (locationMonitor == 1) { - val sharedPreferences = - getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) - val editor = sharedPreferences.edit() - editor.putString("flutter.set_location", setLocation) - Log.d("location", setLocation) - editor.apply() - editor.putInt("flutter.is_location_on", 1) - editor.apply() - val locationAlarmIntent = Intent(this, LocationFetcherService::class.java) - val pendingLocationAlarmIntent = PendingIntent.getService( - this, - 5, - locationAlarmIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - ) - val alarmClockInfo = AlarmManager.AlarmClockInfo(triggerTime - 10000, pendingIntent) - alarmManager.setAlarmClock( - alarmClockInfo, - pendingLocationAlarmIntent - ) - } else if (isWeather == 1) { - val sharedPreferences = - getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) - val editor = sharedPreferences.edit() - editor.putString("flutter.weatherTypes", getWeatherConditions(weatherTypes)) - Log.d("we", getWeatherConditions(weatherTypes)) - editor.apply() - val weatherAlarmIntent = Intent(this, WeatherFetcherService::class.java) - val pendingWeatherAlarmIntent = PendingIntent.getService( - this, - 6, - weatherAlarmIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - ) - val alarmClockInfo = AlarmManager.AlarmClockInfo(triggerTime - 10000, pendingIntent) - alarmManager.setAlarmClock( - alarmClockInfo, - pendingWeatherAlarmIntent - ) - } else { - val alarmClockInfo = AlarmManager.AlarmClockInfo(triggerTime, pendingIntent) - alarmManager.setAlarmClock(alarmClockInfo, pendingIntent) - } - - } - - private fun cancelAllScheduledAlarms() { - val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager - val intent = Intent(this, AlarmReceiver::class.java) - val pendingIntent = PendingIntent.getBroadcast( - this, - 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - ) - - val activityCheckIntent = Intent(this, ScreenMonitorService::class.java) - val pendingActivityCheckIntent = PendingIntent.getService( - this, - 4, - activityCheckIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - ) - - // Cancel any existing alarms by providing the same pending intent - alarmManager.cancel(pendingIntent) - pendingIntent.cancel() - alarmManager.cancel(pendingActivityCheckIntent) - pendingActivityCheckIntent.cancel() - + AlarmScheduler.clear(this) } private fun playDefaultAlarm(context: Context) { @@ -556,4 +446,4 @@ class MainActivity : FlutterActivity() { Log.i("SystemRingtone", "=== END DIAGNOSTICS ===") } -} \ No newline at end of file +} diff --git a/android/app/src/test/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/BootRestorePlannerTest.kt b/android/app/src/test/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/BootRestorePlannerTest.kt new file mode 100644 index 000000000..b94246856 --- /dev/null +++ b/android/app/src/test/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/BootRestorePlannerTest.kt @@ -0,0 +1,146 @@ +package com.ccextractor.ultimate_alarm_clock + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import java.time.LocalDateTime +import java.time.ZoneId + +class BootRestorePlannerTest { + private fun payload(triggerAtMs: Long) = ScheduledAlarmPayload( + triggerAtMs = triggerAtMs, + activityMonitor = 0, + locationMonitor = 0, + location = "", + isWeather = 0, + weatherTypes = "[]" + ) + + @Test + fun `prefers local fallback over persisted payload when both are valid`() { + val now = 1_000L + val persisted = payload(5_000L) + val local = payload(10_000L) + + val reconciled = BootRestorePlanner.chooseAlarmToRestore( + persistedAlarm = persisted, + localAlarm = local, + nowMs = now, + allowLocalFallback = true + ) + + assertEquals(10_000L, reconciled?.triggerAtMs) + } + + @Test + fun `prefers recomputed local alarm when persisted trigger drifted`() { + val now = 1_000L + val persisted = payload(5_000L) + val local = payload(7_200_000L) + + val reconciled = BootRestorePlanner.chooseAlarmToRestore( + persistedAlarm = persisted, + localAlarm = local, + nowMs = now, + allowLocalFallback = true + ) + + assertEquals(7_200_000L, reconciled?.triggerAtMs) + } + + @Test + fun `uses local fallback when persisted payload is missing`() { + val reconciled = BootRestorePlanner.chooseAlarmToRestore( + persistedAlarm = null, + localAlarm = payload(5_000L), + nowMs = 1_000L, + allowLocalFallback = true + ) + + assertEquals(5_000L, reconciled?.triggerAtMs) + } + + @Test + fun `ignores stale persisted payload and falls back to local when allowed`() { + val reconciled = BootRestorePlanner.chooseAlarmToRestore( + persistedAlarm = payload(500L), + localAlarm = payload(5_000L), + nowMs = 1_000L, + allowLocalFallback = true + ) + + assertEquals(5_000L, reconciled?.triggerAtMs) + } + + @Test + fun `does not use local fallback during locked boot recovery`() { + val reconciled = BootRestorePlanner.chooseAlarmToRestore( + persistedAlarm = null, + localAlarm = payload(5_000L), + nowMs = 1_000L, + allowLocalFallback = false + ) + + assertNull(reconciled) + } + + @Test + fun `local resolver computes next repeating trigger using sunday first day string`() { + val zone = ZoneId.systemDefault() + val now = LocalDateTime.of(2026, 3, 12, 13, 38) + .atZone(zone) + .toInstant() + .toEpochMilli() + val alarm = AlarmModel( + id = 1, + minutesSinceMidnight = 13 * 60 + 37, + alarmTime = "13:37", + days = "1111111", + isOneTime = 0, + activityMonitor = 0, + isWeatherEnabled = 0, + weatherTypes = "[]", + isLocationEnabled = 0, + location = "", + alarmDate = "", + alarmId = "alarm-id", + ringOn = 0 + ) + + val triggerAtMs = LocalAlarmScheduleResolver.nextTriggerAtMs(alarm, now, zone) + + val expected = LocalDateTime.of(2026, 3, 13, 13, 37) + .atZone(zone) + .toInstant() + .toEpochMilli() + assertEquals(expected, triggerAtMs) + } + + @Test + fun `local resolver ignores stale one time alarms`() { + val zone = ZoneId.systemDefault() + val now = LocalDateTime.of(2026, 3, 12, 13, 38) + .atZone(zone) + .toInstant() + .toEpochMilli() + val alarm = AlarmModel( + id = 2, + minutesSinceMidnight = 13 * 60 + 37, + alarmTime = "13:37", + days = "0000000", + isOneTime = 1, + activityMonitor = 0, + isWeatherEnabled = 0, + weatherTypes = "[]", + isLocationEnabled = 0, + location = "", + alarmDate = "2026-03-11", + alarmId = "alarm-id", + ringOn = 1 + ) + + val triggerAtMs = LocalAlarmScheduleResolver.nextTriggerAtMs(alarm, now, zone) + + assertNull(triggerAtMs) + } +} diff --git a/android/build.gradle b/android/build.gradle index 5dc5d980d..e1bb5c50a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,21 +1,3 @@ -buildscript { - ext.kotlin_version = '1.7.10' - ext { - compileSdkVersion = 34 - targetSdkVersion = 34 - appCompatVersion = "1.6.1" - } - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.15' - } -} - allprojects { repositories { google() @@ -23,14 +5,37 @@ allprojects { } } -rootProject.buildDir = '../build' +rootProject.buildDir = "../build" subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } + subprojects { - project.evaluationDependsOn(':app') + project.evaluationDependsOn(":app") +} + +subprojects { subproject -> + ["com.android.application", "com.android.library"].each { pluginId -> + subproject.plugins.withId(pluginId) { + def androidExtension = subproject.extensions.findByName("android") + if (androidExtension == null || androidExtension.namespace != null) { + return + } + + def manifestFile = androidExtension.sourceSets.main.manifest.srcFile + if (!manifestFile.exists()) { + return + } + + def manifestPackage = new XmlSlurper().parse(manifestFile).@package.text() + if (manifestPackage) { + androidExtension.namespace = manifestPackage + } + } + } + } tasks.register("clean", Delete) { delete rootProject.buildDir -} \ No newline at end of file +} diff --git a/android/gradle.properties b/android/gradle.properties index ef661b9b5..71e7b0884 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,4 @@ org.gradle.jvmargs=-Xmx4608m android.useAndroidX=true android.enableJetifier=true -android.enableR8=true org.gradle.wrapper.verification=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 532677ec6..e2847c820 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists \ No newline at end of file +zipStorePath=wrapper/dists diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bcf0..264b316e2 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,26 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.9.1" apply false + id "org.jetbrains.kotlin.android" version "2.1.0" apply false + id "com.google.gms.google-services" version "4.4.2" apply false +} + +include ":app" diff --git a/lib/app/data/providers/firestore_provider.dart b/lib/app/data/providers/firestore_provider.dart index e27bd7288..25eef1bc7 100644 --- a/lib/app/data/providers/firestore_provider.dart +++ b/lib/app/data/providers/firestore_provider.dart @@ -5,7 +5,7 @@ import 'package:get/get.dart'; import 'package:ultimate_alarm_clock/app/data/models/alarm_model.dart'; import 'package:ultimate_alarm_clock/app/data/models/user_model.dart'; import 'package:ultimate_alarm_clock/app/data/providers/isar_provider.dart'; -import 'package:ultimate_alarm_clock/app/utils/utils.dart'; +import 'package:ultimate_alarm_clock/app/utils/alarm_schedule_payload.dart'; import 'package:sqflite/sqflite.dart'; import '../../modules/home/controllers/home_controller.dart'; @@ -182,22 +182,9 @@ class FirestoreDb { return alarmRecord; } - int nowInMinutes = 0; - if (wantNextAlarm == true) { - nowInMinutes = Utils.timeOfDayToInt( - TimeOfDay( - hour: TimeOfDay.now().hour, - minute: TimeOfDay.now().minute + 1, - ), - ); - } else { - nowInMinutes = Utils.timeOfDayToInt( - TimeOfDay( - hour: TimeOfDay.now().hour, - minute: TimeOfDay.now().minute + 1, - ), - ); - } + final referenceTime = AlarmSchedulePayload.selectionReferenceTime( + wantNextAlarm: wantNextAlarm, + ); late List alarms; @@ -235,50 +222,37 @@ class FirestoreDb { alarmRecord.minutesSinceMidnight = -1; return alarmRecord; } else { - // Get the closest alarm to the current time - AlarmModel closestAlarm = alarms.reduce((a, b) { - int aTimeUntilNextAlarm = a.minutesSinceMidnight - nowInMinutes; - int bTimeUntilNextAlarm = b.minutesSinceMidnight - nowInMinutes; - - // Check if alarm repeats on any day - bool aRepeats = a.days.any((day) => day); - bool bRepeats = b.days.any((day) => day); - - // If alarm is one-time and has already passed, set time until - // next alarm to next day - if (!aRepeats && aTimeUntilNextAlarm < 0) { - aTimeUntilNextAlarm += Duration.minutesPerDay; - } - if (!bRepeats && bTimeUntilNextAlarm < 0) { - bTimeUntilNextAlarm += Duration.minutesPerDay; - } - - // If alarm repeats on any day, find the next upcoming day - if (aRepeats) { - int currentDay = DateTime.now().weekday - 1; - for (int i = 0; i < a.days.length; i++) { - int dayIndex = (currentDay + i) % a.days.length; - if (a.days[dayIndex]) { - aTimeUntilNextAlarm += i * Duration.minutesPerDay; - break; - } - } - } - - if (bRepeats) { - int currentDay = DateTime.now().weekday - 1; - for (int i = 0; i < b.days.length; i++) { - int dayIndex = (currentDay + i) % b.days.length; - if (b.days[dayIndex]) { - bTimeUntilNextAlarm += i * Duration.minutesPerDay; - break; - } - } - } - - return aTimeUntilNextAlarm < bTimeUntilNextAlarm ? a : b; + final eligibleAlarms = alarms + .where( + (alarm) => + AlarmSchedulePayload.nextTriggerAt( + alarm, + referenceTime: referenceTime, + inclusive: true, + ) != + null, + ) + .toList(); + + if (eligibleAlarms.isEmpty) { + alarmRecord.minutesSinceMidnight = -1; + return alarmRecord; + } + + return eligibleAlarms.reduce((a, b) { + final aTrigger = AlarmSchedulePayload.nextTriggerAt( + a, + referenceTime: referenceTime, + inclusive: true, + )!; + final bTrigger = AlarmSchedulePayload.nextTriggerAt( + b, + referenceTime: referenceTime, + inclusive: true, + )!; + + return aTrigger.isBefore(bTrigger) ? a : b; }); - return closestAlarm; } } diff --git a/lib/app/data/providers/isar_provider.dart b/lib/app/data/providers/isar_provider.dart index 3b15b118a..d64a739ae 100644 --- a/lib/app/data/providers/isar_provider.dart +++ b/lib/app/data/providers/isar_provider.dart @@ -11,7 +11,7 @@ import 'package:ultimate_alarm_clock/app/data/models/saved_emails.dart'; import 'package:ultimate_alarm_clock/app/data/models/timer_model.dart'; import 'package:ultimate_alarm_clock/app/data/providers/firestore_provider.dart'; import 'package:ultimate_alarm_clock/app/data/providers/get_storage_provider.dart'; -import 'package:ultimate_alarm_clock/app/utils/utils.dart'; +import 'package:ultimate_alarm_clock/app/utils/alarm_schedule_payload.dart'; import 'package:sqflite/sqflite.dart'; enum Status { @@ -37,7 +37,6 @@ enum LogType { String toString() => value; } - class IsarDb { static final IsarDb _instance = IsarDb._internal(); late Future db; @@ -171,7 +170,6 @@ class IsarDb { '''); } - Future openDB() async { final dir = await getApplicationDocumentsDirectory(); if (Isar.instanceNames.isEmpty) { @@ -189,7 +187,11 @@ class IsarDb { } return Future.value(Isar.getInstance()); } - Future insertLog(String msg, {Status status = Status.warning, LogType type = LogType.dev, int hasRung = 0}) async { + + Future insertLog(String msg, + {Status status = Status.warning, + LogType type = LogType.dev, + int hasRung = 0}) async { try { final db = await setAlarmLogs(); if (db == null) { @@ -252,7 +254,7 @@ class IsarDb { final isarProvider = IsarDb(); final sql = await IsarDb().getAlarmSQLiteDatabase(); final db = await isarProvider.db; - + await db.writeTxn(() async { await db.alarmModels.put(alarmRecord); }); @@ -287,7 +289,8 @@ class IsarDb { static Future getProfile(String name) async { final isarProvider = IsarDb(); final db = await isarProvider.db; - final a = await db.profileModels.filter().profileNameEqualTo(name).findFirst(); + final a = + await db.profileModels.filter().profileNameEqualTo(name).findFirst(); print('$a appkle'); return a; } @@ -306,7 +309,7 @@ class IsarDb { static Future profileExists(String name) async { final isarProvider = IsarDb(); final db = await isarProvider.db; - final a = + final a = await db.profileModels.filter().profileNameEqualTo(name).findFirst(); return a != null; @@ -337,39 +340,25 @@ class IsarDb { static Future doesAlarmExist(String alarmID) async { final isarProvider = IsarDb(); final db = await isarProvider.db; - final alarms = - await db.alarmModels.where().filter().alarmIDEqualTo(alarmID).findAll(); - print('checkEmpty ${alarms[0].alarmID} ${alarms.isNotEmpty}'); + final alarm = await db.alarmModels + .where() + .filter() + .alarmIDEqualTo(alarmID) + .findFirst(); - return alarms.isNotEmpty; + return alarm != null; } static Future getLatestAlarm( AlarmModel alarmRecord, bool wantNextAlarm, ) async { - int nowInMinutes = 0; final isarProvider = IsarDb(); final db = await isarProvider.db; final currentProfile = await storage.readProfile(); - -// Increasing a day since we need alarms AFTER the current time -// Logically, alarms at current time will ring in the future ;-; - if (wantNextAlarm == true) { - nowInMinutes = Utils.timeOfDayToInt( - TimeOfDay( - hour: TimeOfDay.now().hour, - minute: TimeOfDay.now().minute + 1, - ), - ); - } else { - nowInMinutes = Utils.timeOfDayToInt( - TimeOfDay( - hour: TimeOfDay.now().hour, - minute: TimeOfDay.now().minute, - ), - ); - } + final referenceTime = AlarmSchedulePayload.selectionReferenceTime( + wantNextAlarm: wantNextAlarm, + ); // Get all enabled alarms List alarms = await db.alarmModels @@ -383,51 +372,37 @@ class IsarDb { alarmRecord.minutesSinceMidnight = -1; return alarmRecord; } else { - // Get the closest alarm to the current time - AlarmModel closestAlarm = alarms.reduce((a, b) { - int aTimeUntilNextAlarm = a.minutesSinceMidnight - nowInMinutes; - int bTimeUntilNextAlarm = b.minutesSinceMidnight - nowInMinutes; - - // Check if alarm repeats on any day - bool aRepeats = a.days.any((day) => day); - bool bRepeats = b.days.any((day) => day); - - // If alarm is one-time and has already passed or is happening now, - // set time until next alarm to next day - if (!aRepeats && aTimeUntilNextAlarm < 0) { - aTimeUntilNextAlarm += Duration.minutesPerDay; - } - if (!bRepeats && bTimeUntilNextAlarm < 0) { - bTimeUntilNextAlarm += Duration.minutesPerDay; - } - - // If alarm repeats on any day, find the next upcoming day - if (aRepeats) { - int currentDay = DateTime.now().weekday - 1; - for (int i = 0; i < a.days.length; i++) { - int dayIndex = (currentDay + i) % a.days.length; - if (a.days[dayIndex]) { - aTimeUntilNextAlarm += i * Duration.minutesPerDay; - break; - } - } - } - - if (bRepeats) { - int currentDay = DateTime.now().weekday - 1; - for (int i = 0; i < b.days.length; i++) { - int dayIndex = (currentDay + i) % b.days.length; - if (b.days[dayIndex]) { - bTimeUntilNextAlarm += i * Duration.minutesPerDay; - break; - } - } - } - - return aTimeUntilNextAlarm < bTimeUntilNextAlarm ? a : b; + final eligibleAlarms = alarms + .where( + (alarm) => + AlarmSchedulePayload.nextTriggerAt( + alarm, + referenceTime: referenceTime, + inclusive: true, + ) != + null, + ) + .toList(); + + if (eligibleAlarms.isEmpty) { + alarmRecord.minutesSinceMidnight = -1; + return alarmRecord; + } + + return eligibleAlarms.reduce((a, b) { + final aTrigger = AlarmSchedulePayload.nextTriggerAt( + a, + referenceTime: referenceTime, + inclusive: true, + )!; + final bTrigger = AlarmSchedulePayload.nextTriggerAt( + b, + referenceTime: referenceTime, + inclusive: true, + )!; + + return aTrigger.isBefore(bTrigger) ? a : b; }); - - return closestAlarm; } } @@ -438,7 +413,8 @@ class IsarDb { await db.writeTxn(() async { await db.alarmModels.put(alarmRecord); }); - await IsarDb().insertLog('Alarm updated ${alarmRecord.alarmTime}', status: Status.success, type: LogType.normal); + await IsarDb().insertLog('Alarm updated ${alarmRecord.alarmTime}', + status: Status.success, type: LogType.normal); await sql!.update( 'alarms', alarmRecord.toSQFliteMap(), @@ -447,18 +423,14 @@ class IsarDb { ); } - static Future fixMaxSnoozeCountInAlarms() async { final isarProvider = IsarDb(); final db = await isarProvider.db; final sql = await IsarDb().getAlarmSQLiteDatabase(); - - + final alarms = await db.alarmModels.where().findAll(); - - + for (final alarm in alarms) { - await sql!.update( 'alarms', {'maxSnoozeCount': alarm.maxSnoozeCount}, @@ -768,27 +740,32 @@ class IsarDb { if (ringtoneCount.isEmpty) { await db.writeTxn(() async { await db.ringtoneModels.importJson([ - {'isarId' : fastHash('Digital Alarm 1'), + { + 'isarId': fastHash('Digital Alarm 1'), 'ringtoneName': 'Digital Alarm 1', 'ringtonePath': 'ringtones/digialarm.mp3', 'currentCounterOfUsage': 0 }, - {'isarId' : fastHash('Digital Alarm 2'), + { + 'isarId': fastHash('Digital Alarm 2'), 'ringtoneName': 'Digital Alarm 2', 'ringtonePath': 'ringtones/digialarm2.mp3', 'currentCounterOfUsage': 0 }, - {'isarId' : fastHash('Digital Alarm 3'), + { + 'isarId': fastHash('Digital Alarm 3'), 'ringtoneName': 'Digital Alarm 3', 'ringtonePath': 'ringtones/digialarm3.mp3', 'currentCounterOfUsage': 0 }, - {'isarId' : fastHash('Mystery'), + { + 'isarId': fastHash('Mystery'), 'ringtoneName': 'Mystery', 'ringtonePath': 'ringtones/mystery.mp3', 'currentCounterOfUsage': 0 }, - {'isarId' : fastHash('New Day'), + { + 'isarId': fastHash('New Day'), 'ringtoneName': 'New Day', 'ringtonePath': 'ringtones/newday.mp3', 'currentCounterOfUsage': 0 diff --git a/lib/app/modules/alarmRing/controllers/alarm_ring_controller.dart b/lib/app/modules/alarmRing/controllers/alarm_ring_controller.dart index 01b319d97..10bcbd997 100644 --- a/lib/app/modules/alarmRing/controllers/alarm_ring_controller.dart +++ b/lib/app/modules/alarmRing/controllers/alarm_ring_controller.dart @@ -18,6 +18,7 @@ import 'package:ultimate_alarm_clock/app/data/providers/isar_provider.dart'; import 'package:ultimate_alarm_clock/app/data/providers/secure_storage_provider.dart'; import 'package:ultimate_alarm_clock/app/modules/settings/controllers/settings_controller.dart'; import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.dart'; +import 'package:ultimate_alarm_clock/app/utils/alarm_schedule_payload.dart'; import 'package:ultimate_alarm_clock/app/utils/audio_utils.dart'; import 'package:ultimate_alarm_clock/app/utils/constants.dart'; @@ -59,11 +60,11 @@ class AlarmControlController extends GetxController { UserModel? _userModel = await SecureStorageProvider().retrieveUserModel(); AlarmModel _alarmRecord = homeController.genFakeAlarmModel(); AlarmModel isarLatestAlarm = - await IsarDb.getLatestAlarm(_alarmRecord, true); + await IsarDb.getLatestAlarm(_alarmRecord, true); AlarmModel firestoreLatestAlarm = - await FirestoreDb.getLatestAlarm(_userModel, _alarmRecord, true); + await FirestoreDb.getLatestAlarm(_userModel, _alarmRecord, true); AlarmModel latestAlarm = - Utils.getFirstScheduledAlarm(isarLatestAlarm, firestoreLatestAlarm); + Utils.getFirstScheduledAlarm(isarLatestAlarm, firestoreLatestAlarm); debugPrint('LATEST : ${latestAlarm.alarmTime}'); return latestAlarm; @@ -75,14 +76,14 @@ class AlarmControlController extends GetxController { void startSnooze() async { int actualMaxSnoozeCount = currentlyRingingAlarm.value.maxSnoozeCount; - + if (currentlyRingingAlarm.value.isarId > 0) { final dbAlarm = await IsarDb.getAlarm(currentlyRingingAlarm.value.isarId); if (dbAlarm != null) { actualMaxSnoozeCount = dbAlarm.maxSnoozeCount; } } - + if (snoozeCount.value >= actualMaxSnoozeCount) { Get.snackbar( "Max Snooze Limit", @@ -95,7 +96,7 @@ class AlarmControlController extends GetxController { return; } snoozeCount.value++; - + Vibration.cancel(); vibrationTimer!.cancel(); isSnoozing.value = true; @@ -111,8 +112,8 @@ class AlarmControlController extends GetxController { timer.cancel(); vibrationTimer = Timer.periodic(const Duration(milliseconds: 3500), (Timer timer) { - Vibration.vibrate(pattern: [500, 3000]); - }); + Vibration.vibrate(pattern: [500, 3000]); + }); AudioUtils.playAlarm(alarmRecord: currentlyRingingAlarm.value); @@ -151,7 +152,7 @@ class AlarmControlController extends GetxController { double vol = currentlyRingingAlarm.value.volMin / 10.0; double diff = (currentlyRingingAlarm.value.volMax - - currentlyRingingAlarm.value.volMin) / + currentlyRingingAlarm.value.volMin) / 10.0; int len = currentlyRingingAlarm.value.gradient * 1000; double steps = (diff / 0.01).abs(); @@ -183,10 +184,13 @@ class AlarmControlController extends GetxController { } }); } + void startListeningToFlip() { _sensorSubscription = accelerometerEvents.listen((event) { - if (event.z < -8) { // Device is flipped (screen down) - if (!isSnoozing.value && settingsController.isFlipToSnooze.value == true) { + if (event.z < -8) { + // Device is flipped (screen down) + if (!isSnoozing.value && + settingsController.isFlipToSnooze.value == true) { startSnooze(); } } @@ -259,7 +263,7 @@ class AlarmControlController extends GetxController { void onInit() async { super.onInit(); startListeningToFlip(); - + // Extract alarm and preview flag from arguments final args = Get.arguments; if (args is Map) { @@ -272,18 +276,20 @@ class AlarmControlController extends GetxController { if (currentlyRingingAlarm.value.isarId > 0) { final dbAlarm = await IsarDb.getAlarm(currentlyRingingAlarm.value.isarId); - if (dbAlarm != null && dbAlarm.maxSnoozeCount != currentlyRingingAlarm.value.maxSnoozeCount) { + if (dbAlarm != null && + dbAlarm.maxSnoozeCount != + currentlyRingingAlarm.value.maxSnoozeCount) { currentlyRingingAlarm.value.maxSnoozeCount = dbAlarm.maxSnoozeCount; } } - + if (currentlyRingingAlarm.value.isGuardian) { guardianTimer = Timer.periodic(const Duration(seconds: 1), (timer) { if (guardianCoundown.value == 0) { currentlyRingingAlarm.value.isCall ? Utils.dialNumber(currentlyRingingAlarm.value.guardian) : Utils.sendSMS(currentlyRingingAlarm.value.guardian, - "Your Friend is not waking up \n - Ultimate Alarm Clock"); + "Your Friend is not waking up \n - Ultimate Alarm Clock"); timer.cancel(); } else { guardianCoundown.value = guardianCoundown.value - 1; @@ -302,8 +308,8 @@ class AlarmControlController extends GetxController { vibrationTimer = Timer.periodic(const Duration(milliseconds: 3500), (Timer timer) { - Vibration.vibrate(pattern: [500, 3000]); - }); + Vibration.vibrate(pattern: [500, 3000]); + }); // Preventing app from being minimized! _subscription = FGBGEvents.stream.listen((event) { @@ -358,8 +364,7 @@ class AlarmControlController extends GetxController { AudioUtils.playAlarm(alarmRecord: currentlyRingingAlarm.value); - - if(currentlyRingingAlarm.value.showMotivationalQuote) { + if (currentlyRingingAlarm.value.showMotivationalQuote) { Quote quote = Utils.getRandomQuote(); showQuotePopup(quote); } @@ -372,7 +377,7 @@ class AlarmControlController extends GetxController { // Finding the next alarm to ring AlarmModel latestAlarm = await getNextAlarm(); TimeOfDay latestAlarmTimeOfDay = - Utils.stringToTimeOfDay(latestAlarm.alarmTime); + Utils.stringToTimeOfDay(latestAlarm.alarmTime); // } // This condition will never satisfy because this will only @@ -380,22 +385,17 @@ class AlarmControlController extends GetxController { if (latestAlarm.isEnabled == false) { debugPrint( 'STOPPED IF CONDITION with latest = ' - '${latestAlarmTimeOfDay.toString()} and ' - 'current = ${currentTime.toString()}', + '${latestAlarmTimeOfDay.toString()} and ' + 'current = ${currentTime.toString()}', ); await alarmChannel.invokeMethod('cancelAllScheduledAlarms'); } else { - int intervaltoAlarm = Utils.getMillisecondsToAlarm( - DateTime.now(), - Utils.timeOfDayToDateTime(latestAlarmTimeOfDay), - ); - try { - await alarmChannel.invokeMethod('scheduleAlarm', { - 'milliSeconds': intervaltoAlarm, - 'activityMonitor': latestAlarm.activityMonitor - }); + await alarmChannel.invokeMethod( + 'scheduleAlarm', + AlarmSchedulePayload.fromAlarm(latestAlarm), + ); print("Scheduled..."); } on PlatformException catch (e) { print("Failed to schedule alarm: ${e.message}"); @@ -416,24 +416,23 @@ class AlarmControlController extends GetxController { initialVolume, stream: AudioStream.alarm, ); - + if (!isPreviewMode.value) { if (currentlyRingingAlarm.value.deleteAfterGoesOff == true) { - if (currentlyRingingAlarm.value.isSharedAlarmEnabled && - currentlyRingingAlarm.value.ownerId != null && - currentlyRingingAlarm.value.firestoreId != null) { + if (currentlyRingingAlarm.value.isSharedAlarmEnabled && + currentlyRingingAlarm.value.ownerId != null && + currentlyRingingAlarm.value.firestoreId != null) { await FirestoreDb.deleteOneTimeAlarm( currentlyRingingAlarm.value.ownerId, currentlyRingingAlarm.value.firestoreId, ); } else if (currentlyRingingAlarm.value.isarId > 0) { - await IsarDb.deleteAlarm(currentlyRingingAlarm.value.isarId); } - } - else if (currentlyRingingAlarm.value.days.every((element) => element == false)) { + } else if (currentlyRingingAlarm.value.days + .every((element) => element == false)) { currentlyRingingAlarm.value.isEnabled = false; - if (!currentlyRingingAlarm.value.isSharedAlarmEnabled && + if (!currentlyRingingAlarm.value.isSharedAlarmEnabled && currentlyRingingAlarm.value.isarId > 0) { await IsarDb.updateAlarm(currentlyRingingAlarm.value); } else if (currentlyRingingAlarm.value.ownerId != null) { diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index 449ca94fa..673f8f603 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -17,6 +17,7 @@ import 'package:ultimate_alarm_clock/app/data/providers/get_storage_provider.dar import 'package:ultimate_alarm_clock/app/data/providers/isar_provider.dart'; import 'package:ultimate_alarm_clock/app/data/providers/secure_storage_provider.dart'; import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.dart'; +import 'package:ultimate_alarm_clock/app/utils/alarm_schedule_payload.dart'; import 'package:ultimate_alarm_clock/app/utils/constants.dart'; import 'package:ultimate_alarm_clock/app/utils/utils.dart'; @@ -232,19 +233,16 @@ class HomeController extends GetxController { String profileName = await storage.readProfile(); selectedProfile.value = profileName; ProfileModel? p = await IsarDb.getProfile(profileName); - if (p != null) - { + if (p != null) { profileModel.value = p!; } - } void writeProfileName(String name) async { await storage.writeProfile(name); selectedProfile.value = name; ProfileModel? p = await IsarDb.getProfile(name); - if (p != null) - { + if (p != null) { profileModel.value = p!; } } @@ -261,20 +259,18 @@ class HomeController extends GetxController { readProfileName(); userModel.value = await SecureStorageProvider().retrieveUserModel(); - if (userModel.value == null){ - FirebaseAuth.instance.authStateChanges().listen((user) { - if (user == null) { - isUserSignedIn.value = false; - } else { - isUserSignedIn.value = true; - } - }); - } - else { - isUserSignedIn.value = true; + if (userModel.value == null) { + FirebaseAuth.instance.authStateChanges().listen((user) { + if (user == null) { + isUserSignedIn.value = false; + } else { + isUserSignedIn.value = true; + } + }); + } else { + isUserSignedIn.value = true; } - isSortedAlarmListEnabled.value = await SecureStorageProvider() .readSortedAlarmListValue(key: 'sorted_alarm_list'); @@ -287,7 +283,6 @@ class HomeController extends GetxController { final newFactor = 1.0 - (offset / maxOffset).clamp(0.0, 1.0); scalingFactor.value = (minFactor + (maxFactor - minFactor) * newFactor); }); - } refreshUpcomingAlarms() async { @@ -401,15 +396,11 @@ class HomeController extends GetxController { ); await alarmChannel.invokeMethod('cancelAllScheduledAlarms'); } else { - int intervaltoAlarm = Utils.getMillisecondsToAlarm( - DateTime.now(), - Utils.timeOfDayToDateTime(latestAlarmTimeOfDay), - ); try { - await alarmChannel.invokeMethod('scheduleAlarm', { - 'milliSeconds': intervaltoAlarm, - 'activityMonitor': latestAlarm.activityMonitor, - }); + await alarmChannel.invokeMethod( + 'scheduleAlarm', + AlarmSchedulePayload.fromAlarm(latestAlarm), + ); print('Scheduled...'); } on PlatformException catch (e) { print('Failed to schedule alarm: ${e.message}'); @@ -517,15 +508,14 @@ class HomeController extends GetxController { try { if (isSharedAlarmEnabled) { - - AlarmModel? alarmToDelete = await FirestoreDb.getAlarm(userModel.value, alarmId); + AlarmModel? alarmToDelete = + await FirestoreDb.getAlarm(userModel.value, alarmId); if (alarmToDelete != null) { deletedAlarms.add(alarmToDelete); await FirestoreDb.deleteAlarm(userModel.value, alarmId); successCount++; } } else { - AlarmModel? alarmToDelete = await IsarDb.getAlarm(alarmId); if (alarmToDelete != null) { deletedAlarms.add(alarmToDelete); @@ -557,7 +547,6 @@ class HomeController extends GetxController { ), mainButton: TextButton( onPressed: () async { - for (var alarm in deletedAlarms) { if (alarm.isSharedAlarmEnabled) { await FirestoreDb.addAlarm(userModel.value, alarm); @@ -565,7 +554,7 @@ class HomeController extends GetxController { await IsarDb.addAlarm(alarm); } } - + refreshTimer = true; refreshUpcomingAlarms(); }, @@ -576,7 +565,6 @@ class HomeController extends GetxController { ), ); - selectedAlarmSet.clear(); numberOfAlarmsSelected.value = 0; } else { diff --git a/lib/app/modules/splashScreen/controllers/splash_screen_controller.dart b/lib/app/modules/splashScreen/controllers/splash_screen_controller.dart index 243c482d1..874773a27 100644 --- a/lib/app/modules/splashScreen/controllers/splash_screen_controller.dart +++ b/lib/app/modules/splashScreen/controllers/splash_screen_controller.dart @@ -6,6 +6,7 @@ import 'package:ultimate_alarm_clock/app/data/models/user_model.dart'; import 'package:ultimate_alarm_clock/app/data/providers/firestore_provider.dart'; import 'package:ultimate_alarm_clock/app/data/providers/isar_provider.dart'; import 'package:ultimate_alarm_clock/app/data/providers/secure_storage_provider.dart'; +import 'package:ultimate_alarm_clock/app/utils/alarm_schedule_payload.dart'; import 'package:ultimate_alarm_clock/app/utils/utils.dart'; import '../../home/controllers/home_controller.dart'; @@ -22,8 +23,7 @@ class SplashScreenController extends GetxController { getCurrentlyRingingAlarm() async { AlarmModel _alarmRecord = homeController.genFakeAlarmModel(); - AlarmModel latestAlarm = - await IsarDb.getLatestAlarm(_alarmRecord, false); + AlarmModel latestAlarm = await IsarDb.getLatestAlarm(_alarmRecord, false); debugPrint('CURRENT RINGING : ${latestAlarm.alarmTime}'); return latestAlarm; } @@ -99,9 +99,9 @@ class SplashScreenController extends GetxController { @override void onInit() async { super.onInit(); - + await IsarDb.fixMaxSnoozeCountInAlarms(); - + currentlyRingingAlarm.value = homeController.genFakeAlarmModel(); alarmChannel.setMethodCallHandler((call) async { if (call.method == 'appStartup') { @@ -118,15 +118,20 @@ class SplashScreenController extends GetxController { } else { if (shouldAlarmRing) { currentlyRingingAlarm.value = await getCurrentlyRingingAlarm(); - + if (currentlyRingingAlarm.value.alarmID != null) { - final dbAlarm = await IsarDb.getAlarm(currentlyRingingAlarm.value.isarId); - if (dbAlarm != null && dbAlarm.maxSnoozeCount != currentlyRingingAlarm.value.maxSnoozeCount) { - currentlyRingingAlarm.value.maxSnoozeCount = dbAlarm.maxSnoozeCount; + final dbAlarm = + await IsarDb.getAlarm(currentlyRingingAlarm.value.isarId); + if (dbAlarm != null && + dbAlarm.maxSnoozeCount != + currentlyRingingAlarm.value.maxSnoozeCount) { + currentlyRingingAlarm.value.maxSnoozeCount = + dbAlarm.maxSnoozeCount; } } - - Get.offNamed('/alarm-ring',arguments: currentlyRingingAlarm.value); + + Get.offNamed('/alarm-ring', + arguments: currentlyRingingAlarm.value); } else { currentlyRingingAlarm.value = await getCurrentlyRingingAlarm(); // If the alarm is set to NEVER repeat, then it will be chosen as @@ -156,16 +161,11 @@ class SplashScreenController extends GetxController { '${latestAlarmTimeOfDay.toString()} and '); await alarmChannel.invokeMethod('cancelAllScheduledAlarms'); } else { - int intervaltoAlarm = Utils.getMillisecondsToAlarm( - DateTime.now(), - Utils.timeOfDayToDateTime(latestAlarmTimeOfDay), - ); - try { - await alarmChannel.invokeMethod('scheduleAlarm', { - 'milliSeconds': intervaltoAlarm, - 'activityMonitor': latestAlarm.activityMonitor - }); + await alarmChannel.invokeMethod( + 'scheduleAlarm', + AlarmSchedulePayload.fromAlarm(latestAlarm), + ); print("Scheduled..."); } on PlatformException catch (e) { print("Failed to schedule alarm: ${e.message}"); diff --git a/lib/app/utils/alarm_schedule_payload.dart b/lib/app/utils/alarm_schedule_payload.dart new file mode 100644 index 000000000..69163adf1 --- /dev/null +++ b/lib/app/utils/alarm_schedule_payload.dart @@ -0,0 +1,101 @@ +import 'dart:convert'; + +import 'package:ultimate_alarm_clock/app/data/models/alarm_model.dart'; +import 'package:ultimate_alarm_clock/app/utils/utils.dart'; + +class AlarmSchedulePayload { + static DateTime selectionReferenceTime({ + DateTime? now, + required bool wantNextAlarm, + }) { + final currentTime = now ?? DateTime.now(); + final truncated = DateTime( + currentTime.year, + currentTime.month, + currentTime.day, + currentTime.hour, + currentTime.minute, + ); + + return wantNextAlarm + ? truncated.add(const Duration(minutes: 1)) + : truncated; + } + + static DateTime? nextTriggerAt( + AlarmModel alarm, { + DateTime? referenceTime, + bool inclusive = false, + }) { + final currentTime = referenceTime ?? DateTime.now(); + final alarmTime = Utils.stringToTimeOfDay(alarm.alarmTime); + + bool isValidCandidate(DateTime candidate) { + return inclusive + ? !candidate.isBefore(currentTime) + : candidate.isAfter(currentTime); + } + + DateTime buildCandidate(DateTime date) { + return DateTime( + date.year, + date.month, + date.day, + alarmTime.hour, + alarmTime.minute, + ); + } + + if (alarm.ringOn) { + final scheduledDate = DateTime.tryParse(alarm.alarmDate.trim()); + if (scheduledDate == null) { + return null; + } + + final candidate = buildCandidate(scheduledDate); + return isValidCandidate(candidate) ? candidate : null; + } + + if (alarm.days.any((day) => day)) { + for (var offset = 0; offset <= 7; offset++) { + final candidateDate = currentTime.add(Duration(days: offset)); + final candidate = buildCandidate(candidateDate); + final weekdayIndex = candidate.weekday - 1; + + if (alarm.days[weekdayIndex] && isValidCandidate(candidate)) { + return candidate; + } + } + + return null; + } + + final candidate = buildCandidate(currentTime); + if (isValidCandidate(candidate)) { + return candidate; + } + + return candidate.add(const Duration(days: 1)); + } + + static Map fromAlarm( + AlarmModel alarm, { + DateTime? now, + }) { + final currentTime = now ?? DateTime.now(); + final scheduledTime = nextTriggerAt(alarm, referenceTime: currentTime); + if (scheduledTime == null) { + throw StateError('Alarm does not have a future trigger time'); + } + + return { + 'triggerAtMs': scheduledTime.millisecondsSinceEpoch, + 'milliSeconds': Utils.getMillisecondsToAlarm(currentTime, scheduledTime), + 'activityMonitor': alarm.activityMonitor, + 'locationMonitor': alarm.isLocationEnabled ? 1 : 0, + 'location': alarm.location, + 'isWeather': alarm.isWeatherEnabled ? 1 : 0, + 'weatherTypes': jsonEncode(alarm.weatherTypes), + }; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index ea1939f07..9129cefab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,7 +35,7 @@ dependencies: url_launcher: ^6.3.0 flutter_expandable_fab: ^1.8.1 vibration: ^1.8.1 - file_picker: ^6.1.1 + file_picker: 8.0.7 audioplayers: ^5.2.1 sensors_plus: ^1.4.1 rxdart: ^0.27.7 @@ -66,6 +66,20 @@ dev_dependencies: flutter_test: sdk: flutter +dependency_overrides: + fluttertoast: + path: third_party/pub_patches/fluttertoast + fl_location: + path: third_party/pub_patches/fl_location + flutter_fgbg: + path: third_party/pub_patches/flutter_fgbg + audioplayers_android: + path: third_party/pub_patches/audioplayers_android + sensors_plus: + path: third_party/pub_patches/sensors_plus + vibration: + path: third_party/pub_patches/vibration + flutter_native_splash: android: true ios: true diff --git a/test/app/data/providers/isar_provider_test.dart b/test/app/data/providers/isar_provider_test.dart new file mode 100644 index 000000000..fd128f145 --- /dev/null +++ b/test/app/data/providers/isar_provider_test.dart @@ -0,0 +1,51 @@ +import 'dart:ffi'; +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:isar/isar.dart'; +import 'package:ultimate_alarm_clock/app/data/providers/isar_provider.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + const pathProviderChannel = MethodChannel('plugins.flutter.io/path_provider'); + late Directory tempDirectory; + + setUpAll(() async { + await Isar.initializeIsarCore( + libraries: { + Abi.current(): + '${Platform.environment['HOME']}/.pub-cache/hosted/pub.dev/isar_flutter_libs-3.1.0+1/linux/libisar.so', + }, + ); + + tempDirectory = await Directory.systemTemp.createTemp( + 'ultimate_alarm_clock_isar_test', + ); + + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(pathProviderChannel, (methodCall) async { + if (methodCall.method == 'getApplicationDocumentsDirectory') { + return tempDirectory.path; + } + return null; + }); + }); + + tearDownAll(() async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(pathProviderChannel, null); + + final db = await IsarDb().db; + await db.close(deleteFromDisk: true); + + if (tempDirectory.existsSync()) { + await tempDirectory.delete(recursive: true); + } + }); + + test('doesAlarmExist returns false when the alarm is missing', () async { + expect(await IsarDb.doesAlarmExist('missing-alarm-id'), isFalse); + }); +} diff --git a/test/app/utils/alarm_schedule_payload_test.dart b/test/app/utils/alarm_schedule_payload_test.dart new file mode 100644 index 000000000..98e3d0ed4 --- /dev/null +++ b/test/app/utils/alarm_schedule_payload_test.dart @@ -0,0 +1,141 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:ultimate_alarm_clock/app/data/models/alarm_model.dart'; +import 'package:ultimate_alarm_clock/app/utils/alarm_schedule_payload.dart'; + +AlarmModel buildAlarm() { + return AlarmModel( + alarmTime: '09:00', + alarmID: 'alarm-1', + ownerId: '', + ownerName: '', + lastEditedUserId: '', + mutexLock: false, + days: [false, false, false, false, false, false, false], + intervalToAlarm: 0, + isActivityEnabled: false, + minutesSinceMidnight: 0, + isLocationEnabled: false, + isSharedAlarmEnabled: false, + isWeatherEnabled: false, + location: '', + weatherTypes: const [], + isMathsEnabled: false, + mathsDifficulty: 0, + numMathsQuestions: 0, + isShakeEnabled: false, + shakeTimes: 0, + isQrEnabled: false, + qrValue: '', + isPedometerEnabled: false, + numberOfSteps: 0, + activityInterval: 0, + mainAlarmTime: '09:00', + label: '', + isOneTime: true, + snoozeDuration: 5, + gradient: 0, + ringtoneName: 'Default', + note: '', + deleteAfterGoesOff: false, + showMotivationalQuote: false, + volMax: 1, + volMin: 0, + activityMonitor: 0, + ringOn: false, + alarmDate: '2026-03-12', + profile: 'Default', + isGuardian: false, + guardianTimer: 0, + guardian: '', + isCall: false, + ); +} + +void main() { + test('finds the next enabled weekday for repeating alarms', () { + final alarm = buildAlarm() + ..alarmTime = '08:45' + ..days = [false, false, true, false, true, false, false]; + + final triggerAt = AlarmSchedulePayload.nextTriggerAt( + alarm, + referenceTime: DateTime(2026, 3, 11, 9, 0), + ); + + expect(triggerAt, DateTime(2026, 3, 13, 8, 45)); + }); + + test('respects ringOn date based alarms instead of wrapping to tomorrow', () { + final alarm = buildAlarm() + ..alarmTime = '07:30' + ..ringOn = true + ..alarmDate = '2026-03-15 '; + + final triggerAt = AlarmSchedulePayload.nextTriggerAt( + alarm, + referenceTime: DateTime(2026, 3, 12, 9, 0), + ); + + final payload = AlarmSchedulePayload.fromAlarm( + alarm, + now: DateTime(2026, 3, 12, 9, 0), + ); + + expect(triggerAt, DateTime(2026, 3, 15, 7, 30)); + expect( + payload['triggerAtMs'], + DateTime(2026, 3, 15, 7, 30).millisecondsSinceEpoch, + ); + expect( + payload['milliSeconds'], + const Duration(days: 2, hours: 22, minutes: 30).inMilliseconds, + ); + }); + + test('builds the native scheduling payload from alarm state', () { + final alarm = buildAlarm() + ..alarmTime = '09:30' + ..activityMonitor = 1 + ..isLocationEnabled = true + ..location = '12.9716,77.5946' + ..isWeatherEnabled = true + ..weatherTypes = [1, 3]; + + final payload = AlarmSchedulePayload.fromAlarm( + alarm, + now: DateTime(2026, 3, 12, 9, 0), + ); + + expect( + payload['triggerAtMs'], + DateTime(2026, 3, 12, 9, 30).millisecondsSinceEpoch, + ); + expect(payload['milliSeconds'], 30 * 60 * 1000); + expect(payload['activityMonitor'], 1); + expect(payload['locationMonitor'], 1); + expect(payload['location'], '12.9716,77.5946'); + expect(payload['isWeather'], 1); + expect(payload['weatherTypes'], jsonEncode([1, 3])); + }); + + test('wraps scheduling to the next day when the alarm time already passed', + () { + final alarm = buildAlarm()..alarmTime = '08:45'; + + final payload = AlarmSchedulePayload.fromAlarm( + alarm, + now: DateTime(2026, 3, 12, 9, 0), + ); + + expect( + payload['triggerAtMs'], + DateTime(2026, 3, 13, 8, 45).millisecondsSinceEpoch, + ); + expect(payload['milliSeconds'], ((23 * 60) + 45) * 60 * 1000); + expect(payload['locationMonitor'], 0); + expect(payload['isWeather'], 0); + expect(payload['weatherTypes'], jsonEncode([])); + }); +} diff --git a/third_party/pub_patches/README.md b/third_party/pub_patches/README.md new file mode 100644 index 000000000..01bb4bff9 --- /dev/null +++ b/third_party/pub_patches/README.md @@ -0,0 +1,6 @@ +Project-local patched pub packages used to keep the Android build reproducible. + +These directories were copied from the working patched pub cache used to validate +the Android migration on March 12, 2026. `pubspec.yaml` uses path-based +`dependency_overrides` so CI and other contributors resolve the same plugin +sources without relying on local `.pub-cache` edits. diff --git a/third_party/pub_patches/audioplayers_android/CHANGELOG.md b/third_party/pub_patches/audioplayers_android/CHANGELOG.md new file mode 100644 index 000000000..f941c5b97 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/CHANGELOG.md @@ -0,0 +1,388 @@ +## 4.0.3 + + - **FIX**(android): Released wrong source in LOW_LATENCY mode ([#1672](https://github.com/bluefireteam/audioplayers/issues/1672)). ([d9c5f693](https://github.com/bluefireteam/audioplayers/commit/d9c5f693cafab21b67b785de6244c3c371344a53)) + +## 4.0.2 + + - **REFACTOR**: Lint Kotlin, C and C++ code ([#1610](https://github.com/bluefireteam/audioplayers/issues/1610)). ([05394668](https://github.com/bluefireteam/audioplayers/commit/0539466850aaa49a0bde9448939c6c3d536dd6e2)) + - **FIX**: Set playback rate only when playing ([#1658](https://github.com/bluefireteam/audioplayers/issues/1658)). ([d73c7d5c](https://github.com/bluefireteam/audioplayers/commit/d73c7d5c2ef13e8eff2c438b96ade6e2483a2014)) + - **FIX**: Improve Error handling for Unsupported Sources ([#1625](https://github.com/bluefireteam/audioplayers/issues/1625)). ([a4d84422](https://github.com/bluefireteam/audioplayers/commit/a4d84422f1421755b05aa7eff38b4d2ed0cf7482)) + - **FIX**: Return null for duration and position, if not available ([#1606](https://github.com/bluefireteam/audioplayers/issues/1606)). ([2a79644a](https://github.com/bluefireteam/audioplayers/commit/2a79644a2064ccc5d8e9a31aaf888b0b60ee321d)) + +## 4.0.1 + + - **REVERT**(android): Upgrade androidx.core:core-ktx, restore support for AGP7 ([#1590](https://github.com/bluefireteam/audioplayers/issues/1590)). ([f6bf1260](https://github.com/bluefireteam/audioplayers/commit/f6bf12609ec9e457451f1c786522bff28a1555f4)) + +## 4.0.0 + +> Note: This release has breaking changes. + + - **FIX**(android): Allow AudioFocus.none ([#1534](https://github.com/bluefireteam/audioplayers/issues/1534)). ([858d3f44](https://github.com/bluefireteam/audioplayers/commit/858d3f4410b1bc7b203090c20cf60b5136dad4fe)) + - **FEAT**(android): Add support for AGP 8 in example, add compileOptions to build.gradle ([#1503](https://github.com/bluefireteam/audioplayers/issues/1503)). ([7c08e4e1](https://github.com/bluefireteam/audioplayers/commit/7c08e4e1a524f53294f6967996fd31837e62cb81)) + - **BREAKING** **FIX**: Default audio output to system preferences ([#1563](https://github.com/bluefireteam/audioplayers/issues/1563)). ([381c43e3](https://github.com/bluefireteam/audioplayers/commit/381c43e3725fbb0cb4fd35982893a3c92b188886)) + - **BREAKING** **CHORE**: Bump Flutter to version 3.10.x ([#1529](https://github.com/bluefireteam/audioplayers/issues/1529)). ([c1296c9b](https://github.com/bluefireteam/audioplayers/commit/c1296c9ba0cc43284b31d78f2f484454fbf6b773)) + +## 3.0.2 + + - **FIX**(android): `onComplete` is not called when audio has completed playing ([#1523](https://github.com/bluefireteam/audioplayers/issues/1523)). ([293d6c0e](https://github.com/bluefireteam/audioplayers/commit/293d6c0eec1d89ad200b2914cae0adf644b25013)) + - **FIX**: Timeout on setting same source twice ([#1520](https://github.com/bluefireteam/audioplayers/issues/1520)). ([5d164d1f](https://github.com/bluefireteam/audioplayers/commit/5d164d1f20463a8a31a228cd1d85252d47ae256e)) + - **FIX**: test and fix compatibility with min flutter version ([#1510](https://github.com/bluefireteam/audioplayers/issues/1510)). ([9f39e95f](https://github.com/bluefireteam/audioplayers/commit/9f39e95ff7913d8fc30fff27fef7aefc32de26fb)) + - **FIX**(android): Add AGP 8 support with namespace property ([#1514](https://github.com/bluefireteam/audioplayers/issues/1514)). ([8d7b322e](https://github.com/bluefireteam/audioplayers/commit/8d7b322e79fd802fb75ca72f5c8ac388754cd406)) + - **FIX**: onPrepared event to wait until player is ready / finished loading the source ([#1469](https://github.com/bluefireteam/audioplayers/issues/1469)). ([50f56365](https://github.com/bluefireteam/audioplayers/commit/50f56365f8e512df0fc5bdb7222614389cbd4ea0)) + - **FIX**: rework dispose ([#1480](https://github.com/bluefireteam/audioplayers/issues/1480)). ([c64ef6d9](https://github.com/bluefireteam/audioplayers/commit/c64ef6d914a52743128c717b90c4da0abbd7538d)) + +## 3.0.1 + + - **FIX**: dispose player implementation ([#1470](https://github.com/bluefireteam/audioplayers/issues/1470)). ([d9026c15](https://github.com/bluefireteam/audioplayers/commit/d9026c1538cc83dfba5745771ad71c307b6da852)) + +## 3.0.0 + +> Note: This release has breaking changes. + + - **FIX**(android): Avoid calling onDuration on position event (closes [#136](https://github.com/bluefireteam/audioplayers/issues/136)) ([#1460](https://github.com/bluefireteam/audioplayers/issues/1460)). ([6cfb3753](https://github.com/bluefireteam/audioplayers/commit/6cfb3753cd8003f341d97e0b2417d4512f452267)) + - **FIX**(android): reset prepared state on player error ([#1425](https://github.com/bluefireteam/audioplayers/issues/1425)). ([6f24c8f5](https://github.com/bluefireteam/audioplayers/commit/6f24c8f57e4549edbf7d68a021d1d94371c23f3f)) + - **FEAT**(android): add `setBalance` ([#58](https://github.com/bluefireteam/audioplayers/issues/58)) ([#1444](https://github.com/bluefireteam/audioplayers/issues/1444)). ([3b5de50e](https://github.com/bluefireteam/audioplayers/commit/3b5de50ea7fa5248165616fc1ffd80da6c66583a)) + - **DOCS**: update AudioCache explanation, migration guide, replace package READMEs ([#1457](https://github.com/bluefireteam/audioplayers/issues/1457)). ([b8eb1974](https://github.com/bluefireteam/audioplayers/commit/b8eb197435631fafeaa9a26eb76aca8e43e86420)) + - **BREAKING** **FEAT**: event channel ([#1352](https://github.com/bluefireteam/audioplayers/issues/1352)). ([c9fd6a76](https://github.com/bluefireteam/audioplayers/commit/c9fd6a762c8c346d8d5598e3550c5571a5e460f0)) + +## 2.0.0 + +> Note: This release has breaking changes. + + - **FIX**: playing at playback rate `1.0` in android API level < 23 (fixes [#1344](https://github.com/bluefireteam/audioplayers/issues/1344)) ([#1390](https://github.com/bluefireteam/audioplayers/issues/1390)). ([b248e71d](https://github.com/bluefireteam/audioplayers/commit/b248e71dabf923072f1fd14355b4e0230c9a6593)) + - **BREAKING** **FEAT**: configurable SoundPool and `AudioManager.mode` ([#1388](https://github.com/bluefireteam/audioplayers/issues/1388)). ([5697f187](https://github.com/bluefireteam/audioplayers/commit/5697f187bcca64de2e519f8f49aaf4817fcf6398)) + +## 1.1.4 + + - Update a dependency to the latest release. + +## 1.1.3 + + - **FIX**: Avoid ConcurrentModificationException ([#1297](https://github.com/bluefireteam/audioplayers/issues/1297)). ([d15ef5ab](https://github.com/bluefireteam/audioplayers/commit/d15ef5ab93f11e2f19089af08f1533fcdc1397e6)) + - **DOCS**: Fix repos and homepages on pubspecs ([#1349](https://github.com/bluefireteam/audioplayers/issues/1349)). ([0bdde4d9](https://github.com/bluefireteam/audioplayers/commit/0bdde4d9f8f62487cdcfe96221216eba03b31060)) + +## 1.1.1 + + - **FIX**: Avoid ConcurrentModificationException ([#1297](https://github.com/bluefireteam/audioplayers/issues/1297)). ([d15ef5ab](https://github.com/bluefireteam/audioplayers/commit/d15ef5ab93f11e2f19089af08f1533fcdc1397e6)) + +## 1.1.0 + + - **FIX**: lowLatency bugs (closes #1176, closes #1193, closes #1165) (#1272). ([541578cc](https://github.com/bluefireteam/audioplayers/commit/541578cc50f3856c23c393faa1a71380b3b49222)) + - **FIX**: revert compileSdkVersion to be compatible with flutter.compileSdkVersion (#1273). ([0b9fed43](https://github.com/bluefireteam/audioplayers/commit/0b9fed43d9dfa90870826dc9a34d1a0d730bd78d)) + - **FIX**: emit onPositionChanged when seek is completed (closes #1259) (#1265). ([be7ac6a9](https://github.com/bluefireteam/audioplayers/commit/be7ac6a957fccadf5bcecf0f1fbea197d32bda21)) + - **FIX**: bugs from integration tests (#1247). ([6fad1cc4](https://github.com/bluefireteam/audioplayers/commit/6fad1cc4443e623e5c94519f130b4004b2dc3857)) + - **FIX**: Fix lowLatency mode for Android (#1193) (#1224). ([a25ca284](https://github.com/bluefireteam/audioplayers/commit/a25ca284835252147c85944575c7e71a3ef6abc4)) + - **FEAT**: wait for source to be prepared (#1191). ([5eeca894](https://github.com/bluefireteam/audioplayers/commit/5eeca8940e764546023567fa2f6b1bc3802f97d3)) + +## 1.0.1 + + - **FIX**: getDuration, getPosition causes MEDIA_ERROR_UNKNOWN (#1172). ([51b4c73e](https://github.com/bluefireteam/audioplayers/commit/51b4c73eaff5c60d1c3c3e42ae783df07d34be09)) + +## 1.0.0 + + - **FEAT**: Upgrade flame lint dependency (#1132). ([0d6dae3e](https://github.com/bluefireteam/audioplayers/commit/0d6dae3efc4a73abeb554fd0862d64fda0269066)) + +## 1.0.0-rc.2 + +## 1.0.0-rc.1 + + - First release after federation + +# Changelog + +## 0.20.2 +- Fix bug with inversed log levels + +## 0.20.1 +- Fix enum parsing on release mode on android + +## 0.20.0 +- Fix android/kotlin build for old projects +- Add method to clearNotification +- Add currentPosition stream on web +- Add seek on web +- Add a proper Logger +- Make setPlaybackRate signature consistent +- Fix fatal exception on Android API < 21 in WrappedMediaPlayer.kt setAttributes +- Add clearNotification method + +## 0.19.1 +- Add missing awaits for AudioCache +- Fix Kotlin Core version to v1.6.0 +- Fix iOS warning +- Fix README link to audio_cache.md to work on pub +- Fix documentation referencing old class +- Add web support for audioPlayer.getCurrentPosition +- Add web support for audioPlayer.getDuration +- Add web support for audioPlayer.setPlaybackRate +- Fix local file playback in LOW_LATENCY mode on Android + +## 0.19.0 +- Refactor Notifications code (small breaking changes) +- AudioCache for web +- Fixing basic features for Android lower than API 23 +- Fixing error after playing music several times with AudioCache +- Re-organize folder and file structure on the Dart side (project layout) +- Re-organize folders into a mono-repo +- Fix several bugs + +## 0.18.3 +- Fix Float vs Double mixup on Swift that prevent non-integer values for volume/playback +- Fix open sink issue / resource leak + +## 0.18.2 +- Changing Android minSdk verison to 16 +- Improve build processes and other small bug fixes + +## 0.18.1 +- Fix kotlin config issue for some apps +- Fix warning from pub +- Fix iOS lock screen +- Fix setUrl method + +## 0.18.0 +- Stable null-safety release +- Removed all the `@deprecated` code blocks + +## 0.17.4 +- Fix java.lang.UnsupportedOperationException on read-only kotlin map + +## 0.17.3 +- Backport some code to old kt (for now) + +## 0.17.2 +- Fix macos compilation issue +- Fix android for non-kotlin projects + +## 0.17.1 +- Use better algorithm for speed modulation on iOS +- Extracted and refactored all the notifications code onto the new file +- Add more checks and make sure notifcations code is not ran when it shouldn't +- Add more useful info to the troubleshoot guide + +## 0.17.0 +- Swift conversion of the darwin code + +## 0.16.2 +- Overhauled our contributing guidelines +- Improve docs around player state +- Update dependencies versions + +## 0.16.1 +- Fix Exception thrown when calling audioPlayer.dispose +- Fix bug with AudioCache crash on iOS + +## 0.16.0 +- Implemented stream routing for iOS +- Call release on dispose +- Fix iOS build +- Breaking change audio cache prefix in order to allow override 'assets' + +## audioplayers 0.15.1 +- Fix web for release mode + +## audioplayers 0.15.0 +- Improve loop/readme for web support +- Audio cache support for web +- Re-adding partial web support + +## audioplayers 0.14.3 +- Add next and previous command for ios + +## audioplayers 0.14.2 +- Fix pubspec problem because of web file + +## audioplayers 0.14.1 +- Adding linter, tests and flutter_driver integration tests to a CI (github actions) +- Minor fixes to the APIs and documentation +- Fix restarting the playback of a failed AVPlayerItem +- Prevent exceptions when null values are passed to notifications center +- Prevent crash by checking if headlessServiceInitialized before invoking onNotificationBackgroundPlayerStateChanged + +## audioplayers 0.14.0 +- Adding macOs support +- ios:fix lack of seek completion handle +- ios Delay start fixed + +## audioplayers 0.13.7 +- Bump dependencies, improve gitignore +- Upgrade pubspec pattern + +## audioplayers 0.13.6 +- added `setPlaybackRate` feature for Android +- Automatic detect address is local or remote (thanks, @saeed-golshan) + +## audioplayers 0.13.5 +- fixed crash on iOS when `startHeadlessService()` wasn't called on `AudioPlayer` (by @JesseScott) + +## audioplayers 0.13.4 +- fixing missing cleanup on hot restart on Android +- Background notification updates on iOS + +## audioplayers 0.13.3 +- audio notification area fixes +- fix when other apps are playing sounds +- fix android race condition +- Support for registering plugin in background enviroment +- fix typos and docs + +## audioplayers 0.13.2 +- Handling plugin dealloc and onTimeInterval crashs (thanks @chedechao111) +- Audio position update when the audio is paused (thanks @bjornjacobs) + +## audioplayers 0.13.1 +- Added stayAwake feature (thanks, @danielR2001) +- Improved dispose method (thanks, @hugocbpassos) +- Added getCurrentPosition (thanks, @hariom08) +- Some bug fixes and small changes + +## audioplayers 0.13.0 +- Call onDurationChanged after setUrl() to be consistent with ios version (thanks @subhash279) +- Adding getDuration feature iOS/Android (thanks @alecorsino) + +## audioplayers 0.12.1 +- Fixes bug where the stream handlers were not called due to exception on the handler +- Proper error message when errors in the dart handler occurs + +## audioplayers 0.12.0 +- Update to path_provider 1.1.0 +- Upgrade to Swift 5 in example project setting (thanks @jerryzhoujw) + +## audioplayers 0.11.0 +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## audioplayers 0.10.1 +- Seek and play now works with milliseconds instead of second (thanks, @catoldcui and @erickzanardo) + +## audioplayers 0.10.0 +- Added a low latency api for android (thanks, @feroult) + +## audioplayers 0.9.0 +- Improved callbacks using Streams to allow for multiple subscibers (thanks, @LucasCLuk) +- Update uuid version to 2.0.0 (thanks, @BeMacized) + +## audioplayers 0.8.2 +- Update path_provider version (thanks, @apiraino) + +## audioplayers 0.8.1 +- Fix for duration when playing a stream +- Added respectSilence flag in audioplayers, or isNotification for play methos in audio_cache + False by default, to use player for local notification. Silent when device is in silent mode. + +## audioplayers 0.8.0 +- Allow setting seek position in play function (thanks @rob-patchett) +- Get duration from the underlaying asset instead of from AVPlayerItem (thanks @andressade) +- Adding player state (thanks @renancaraujo) +- Set the audio session to active (thanks @benwicks) +- Delay seek operations on Android until player is ready (thanks @jeffmikels) + +## audioplayers 0.7.8 +- Fix bug regarding name clash with other plugins (thanks @imtaehyun) + +## audioplayers 0.7.7 +- Fix bug when using nested files with audio cache (thanks @hotstu for reporting and @eclewlow for fixing) + +## audioplayers 0.7.6 +- Fix the nefarious bug of 'sound only playing through headphones' (thanks so much, @tsun424) + +## audioplayers 0.7.5 +- Fix SDK constraint for Dart 2.1 (thanks @snoofer and @sroddy) + +## audioplayers 0.7.4 +- Some more fixes to work without errors with Dart 2 stronger types + +## audioplayers 0.7.3 +- Support Android SDK 16-20 (thanks, @sroddy) +- Avoid restarting a looping player if is stopped (thanks, @sroddy) + +## audioplayers 0.7.2 +- Bug fixes for iOS + +## audioplayers 0.7.1 +- Formatting + +## audioplayers 0.7.0 + +- Improved lifecycle handling for android +- Big performance boots +- Allows for finer control of releasing (with setReleaseMode, setUrl, resume, release) +- Allows for setting the volume at any time (with setVolume) +- Added LOOP as a ReleaseMode options, making it significantly faster +- Some other refactorings + +## audioplayers 0.6.0 + +- Major Refactoring! +- Renaming everything to audioplayers (mind the s) +- Better logging +- Added AudioCache (imported from Flame) +- Adding tests! +- Adding better example +- Greatly improving README +- Lots of other minor tweaks + +## audioplayers 0.5.2 + +- don't call the onClomplete hook when you manually stop the audio + +## audioplayers 0.5.1 + +- fix for dart 2 (thanks to @efortuna) + +## audioplayers 0.5.0 + +- improves Android performance by not calling `prepare` on the main thread + +## audioplayers 0.4.1 + +- fix `seek` for iOS + +## audioplayers 0.4.0 + +- volume controls + +## audioplayers 0.3.0 + +- working on iOS (thanks @feroult <3) + +## audioplayers 0.2.0 + +- adding disable log option + +## audioplayers 0.1.0 + +- support for multiple audios simultaneously + +## 0.2.0 + +- support for local files + +## 0.1.0 + +- update to the current Plugin API +- move to https://github.com/rxlabz/audioplayer + +## 0.0.2 + +Separated handlers for position, duration, completion and errors + +- setDurationHandler(TimeChangeHandler handler) +- setPositionHandler(TimeChangeHandler handler) +- setCompletionHandler(VoidCallback callback) +- setErrorHandler(ErrorHandler handler) + +- new typedef +```dart +typedef void TimeChangeHandler(Duration duration); +typedef void ErrorHandler(String message); +``` + +## 0.0.1 + +- first POC : + - methods : play, pause, stop + - a globalHandler for position, duration, completion and errors diff --git a/third_party/pub_patches/audioplayers_android/LICENSE b/third_party/pub_patches/audioplayers_android/LICENSE new file mode 100644 index 000000000..382de332d --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Luan Nico + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/third_party/pub_patches/audioplayers_android/README.md b/third_party/pub_patches/audioplayers_android/README.md new file mode 100644 index 000000000..b16680c0a --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/README.md @@ -0,0 +1,23 @@ +

+ + AudioPlayers + +

+ +--- + +# audioplayers_android +

+ + + + +

+ +The Android implementation of [`audioplayers`](https://pub.dev/packages/audioplayers). + +## Usage + +This package is [endorsed](https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin), +which means you can simply use `audioplayers` normally. +This package will be automatically included in your app when you do, so you do not need to add it to your `pubspec.yaml`. diff --git a/third_party/pub_patches/audioplayers_android/analysis_options.yaml b/third_party/pub_patches/audioplayers_android/analysis_options.yaml new file mode 100644 index 000000000..85732fa02 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options.yaml diff --git a/third_party/pub_patches/audioplayers_android/android/build.gradle b/third_party/pub_patches/audioplayers_android/android/build.gradle new file mode 100644 index 000000000..41a562d7e --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/build.gradle @@ -0,0 +1,80 @@ +group 'xyz.luan.audioplayers' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.10' + ext.coroutines_version = '1.6.4' + + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.3.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "de.mannodermaus.gradle.plugins:android-junit5:1.7.1.1" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'de.mannodermaus.android-junit5' + +android { + compileSdk 33 + + // Conditional for compatibility with AGP <4.2. + if (project.android.hasProperty('namespace')) { + namespace 'xyz.luan.audioplayers' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = '17' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + minSdkVersion 16 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + lint { + disable 'InvalidPackage' + } +} + +allprojects { + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" + } + } +} + +dependencies { + implementation "androidx.core:core-ktx:1.9.0" // Do not pump unless dropping support for AGP7 + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' + testImplementation 'org.assertj:assertj-core:3.23.1' +} +repositories { + mavenCentral() +} diff --git a/third_party/pub_patches/audioplayers_android/android/gradle.properties b/third_party/pub_patches/audioplayers_android/android/gradle.properties new file mode 100644 index 000000000..d9cf55df7 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true diff --git a/third_party/pub_patches/audioplayers_android/android/settings.gradle b/third_party/pub_patches/audioplayers_android/android/settings.gradle new file mode 100644 index 000000000..096aeb19c --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'audioplayers_android' diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/AndroidManifest.xml b/third_party/pub_patches/audioplayers_android/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..0f77d9bf9 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/AudioContextAndroid.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/AudioContextAndroid.kt new file mode 100644 index 000000000..eabbb50b9 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/AudioContextAndroid.kt @@ -0,0 +1,69 @@ +package xyz.luan.audioplayers + +import android.annotation.SuppressLint +import android.media.AudioAttributes +import android.media.AudioAttributes.Builder +import android.media.AudioAttributes.CONTENT_TYPE_MUSIC +import android.media.AudioAttributes.USAGE_MEDIA +import android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE +import android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION +import android.media.AudioManager +import android.media.MediaPlayer +import android.os.Build +import androidx.annotation.RequiresApi +import java.util.* + +data class AudioContextAndroid( + val isSpeakerphoneOn: Boolean, + val stayAwake: Boolean, + val contentType: Int, + val usageType: Int, + val audioFocus: Int, + val audioMode: Int, +) { + @SuppressLint("InlinedApi") // we are just using numerical constants + constructor() : this( + isSpeakerphoneOn = false, + stayAwake = false, + contentType = CONTENT_TYPE_MUSIC, + usageType = USAGE_MEDIA, + audioFocus = AudioManager.AUDIOFOCUS_GAIN, + audioMode = AudioManager.MODE_NORMAL, + ) + + fun setAttributesOnPlayer(player: MediaPlayer) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + player.setAudioAttributes(buildAttributes()) + } else { + @Suppress("DEPRECATION") + player.setAudioStreamType(getStreamType()) + } + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + fun buildAttributes(): AudioAttributes { + return Builder() + .setUsage(usageType) + .setContentType(contentType) + .build() + } + + @Deprecated("This is used for Android older than LOLLIPOP", replaceWith = ReplaceWith("buildAttributes")) + private fun getStreamType(): Int { + return when (usageType) { + USAGE_VOICE_COMMUNICATION -> AudioManager.STREAM_VOICE_CALL + USAGE_NOTIFICATION_RINGTONE -> AudioManager.STREAM_RING + else -> AudioManager.STREAM_MUSIC + } + } + + override fun hashCode() = Objects.hash(isSpeakerphoneOn, stayAwake, contentType, usageType, audioFocus, audioMode) + + override fun equals(other: Any?) = (other is AudioContextAndroid) && + isSpeakerphoneOn == other.isSpeakerphoneOn && + stayAwake == other.stayAwake && + contentType == other.contentType && + usageType == other.usageType && + audioFocus == other.audioFocus && + audioMode == other.audioMode +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/AudioplayersPlugin.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/AudioplayersPlugin.kt new file mode 100644 index 000000000..b220aed15 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/AudioplayersPlugin.kt @@ -0,0 +1,385 @@ +package xyz.luan.audioplayers + +import android.content.Context +import android.media.AudioManager +import android.os.Build +import android.os.Handler +import android.os.Looper +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import xyz.luan.audioplayers.player.SoundPoolManager +import xyz.luan.audioplayers.player.WrappedPlayer +import xyz.luan.audioplayers.source.BytesSource +import xyz.luan.audioplayers.source.UrlSource +import java.io.FileNotFoundException +import java.lang.ref.WeakReference +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap + +typealias FlutterHandler = (call: MethodCall, response: MethodChannel.Result) -> Unit + +class AudioplayersPlugin : FlutterPlugin, IUpdateCallback { + private val mainScope = CoroutineScope(Dispatchers.Main) + + private lateinit var methods: MethodChannel + private lateinit var globalMethods: MethodChannel + private lateinit var globalEvents: EventHandler + private lateinit var context: Context + private lateinit var binaryMessenger: BinaryMessenger + private lateinit var soundPoolManager: SoundPoolManager + + private val players = ConcurrentHashMap() + private val handler = Handler(Looper.getMainLooper()) + private var updateRunnable: Runnable? = null + + private var defaultAudioContext = AudioContextAndroid() + + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + context = binding.applicationContext + binaryMessenger = binding.binaryMessenger + soundPoolManager = SoundPoolManager(this) + methods = MethodChannel(binding.binaryMessenger, "xyz.luan/audioplayers") + methods.setMethodCallHandler { call, response -> safeCall(call, response, ::methodHandler) } + globalMethods = MethodChannel(binding.binaryMessenger, "xyz.luan/audioplayers.global") + globalMethods.setMethodCallHandler { call, response -> safeCall(call, response, ::globalMethodHandler) } + updateRunnable = UpdateRunnable(players, methods, handler, this) + globalEvents = EventHandler(EventChannel(binding.binaryMessenger, "xyz.luan/audioplayers.global/events")) + } + + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + stopUpdates() + handler.removeCallbacksAndMessages(null) + updateRunnable = null + players.values.forEach { it.dispose() } + players.clear() + mainScope.cancel() + soundPoolManager.dispose() + globalEvents.dispose() + } + + private fun safeCall( + call: MethodCall, + response: MethodChannel.Result, + handler: FlutterHandler, + ) { + mainScope.launch(Dispatchers.IO) { + try { + handler(call, response) + } catch (e: Exception) { + response.error("Unexpected AndroidAudioError", e.message, e) + } + } + } + + private fun globalMethodHandler(call: MethodCall, response: MethodChannel.Result) { + when (call.method) { + "setAudioContext" -> { + val audioManager = getAudioManager() + audioManager.mode = defaultAudioContext.audioMode + audioManager.isSpeakerphoneOn = defaultAudioContext.isSpeakerphoneOn + + defaultAudioContext = call.audioContext() + } + + "emitLog" -> { + val message = call.argument("message") ?: error("message is required") + handleGlobalLog(message) + } + + "emitError" -> { + val code = call.argument("code") ?: error("code is required") + val message = call.argument("message") ?: error("message is required") + handleGlobalError(code, message, null) + } + + else -> { + response.notImplemented() + return + } + } + + response.success(1) + } + + private fun methodHandler(call: MethodCall, response: MethodChannel.Result) { + val playerId = call.argument("playerId") ?: return + if (call.method == "create") { + val eventHandler = EventHandler(EventChannel(binaryMessenger, "xyz.luan/audioplayers/events/$playerId")) + players[playerId] = WrappedPlayer(this, eventHandler, defaultAudioContext.copy(), soundPoolManager) + response.success(1) + return + } + val player = getPlayer(playerId) + try { + when (call.method) { + "setSourceUrl" -> { + val url = call.argument("url") ?: error("url is required") + val isLocal = call.argument("isLocal") ?: false + try { + player.source = UrlSource(url, isLocal) + } catch (e: FileNotFoundException) { + response.error( + "AndroidAudioError", + "Failed to set source. For troubleshooting, see: " + + "https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md", + e, + ) + return + } + } + + "setSourceBytes" -> { + val bytes = call.argument("bytes") ?: error("bytes are required") + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + error("Operation not supported on Android <= M") + } + player.source = BytesSource(bytes) + } + + "resume" -> player.play() + "pause" -> player.pause() + "stop" -> player.stop() + "release" -> player.release() + "seek" -> { + val position = call.argument("position") ?: error("position is required") + player.seek(position) + } + + "setVolume" -> { + val volume = call.argument("volume") ?: error("volume is required") + player.volume = volume.toFloat() + } + + "setBalance" -> { + val balance = call.argument("balance") ?: error("balance is required") + player.balance = balance.toFloat() + } + + "setPlaybackRate" -> { + val rate = call.argument("playbackRate") ?: error("playbackRate is required") + player.rate = rate.toFloat() + } + + "getDuration" -> { + response.success(player.getDuration()) + return + } + + "getCurrentPosition" -> { + response.success(player.getCurrentPosition()) + return + } + + "setReleaseMode" -> { + val releaseMode = call.enumArgument("releaseMode") ?: error("releaseMode is required") + player.releaseMode = releaseMode + } + + "setPlayerMode" -> { + val playerMode = call.enumArgument("playerMode") ?: error("playerMode is required") + player.playerMode = playerMode + } + + "setAudioContext" -> { + val audioContext = call.audioContext() + player.updateAudioContext(audioContext) + } + + "emitLog" -> { + val message = call.argument("message") ?: error("message is required") + player.handleLog(message) + } + + "emitError" -> { + val code = call.argument("code") ?: error("code is required") + val message = call.argument("message") ?: error("message is required") + player.handleError(code, message, null) + } + + "dispose" -> { + handler.post { + player.dispose() + players.remove(playerId) + } + } + + else -> { + response.notImplemented() + return + } + } + response.success(1) + } catch (e: Exception) { + response.error("AndroidAudioError", e.message, e) + } + } + + private fun getPlayer(playerId: String): WrappedPlayer { + return players[playerId] ?: error("Player has not yet been created or has already been disposed.") + } + + fun getApplicationContext(): Context { + return context.applicationContext + } + + fun getAudioManager(): AudioManager { + return context.applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager + } + + fun handleIsPlaying() { + startUpdates() + } + + fun handleDuration(player: WrappedPlayer) { + handler.post { + player.eventHandler.success( + "audio.onDuration", + hashMapOf("value" to (player.getDuration() ?: 0)), + ) + } + } + + fun handleComplete(player: WrappedPlayer) { + handler.post { player.eventHandler.success("audio.onComplete") } + } + + fun handlePrepared(player: WrappedPlayer, isPrepared: Boolean) { + handler.post { player.eventHandler.success("audio.onPrepared", hashMapOf("value" to isPrepared)) } + } + + fun handleLog(player: WrappedPlayer, message: String) { + handler.post { player.eventHandler.success("audio.onLog", hashMapOf("value" to message)) } + } + + fun handleGlobalLog(message: String) { + handler.post { globalEvents.success("audio.onLog", hashMapOf("value" to message)) } + } + + fun handleError(player: WrappedPlayer, errorCode: String?, errorMessage: String?, errorDetails: Any?) { + handler.post { player.eventHandler.error(errorCode, errorMessage, errorDetails) } + } + + fun handleGlobalError(errorCode: String?, errorMessage: String?, errorDetails: Any?) { + handler.post { globalEvents.error(errorCode, errorMessage, errorDetails) } + } + + fun handleSeekComplete(player: WrappedPlayer) { + handler.post { + player.eventHandler.success("audio.onSeekComplete") + player.eventHandler.success( + "audio.onCurrentPosition", + hashMapOf("value" to (player.getCurrentPosition() ?: 0)), + ) + } + } + + override fun startUpdates() { + updateRunnable?.let { handler.post(it) } + } + + override fun stopUpdates() { + updateRunnable?.let { handler.removeCallbacks(it) } + } + + private class UpdateRunnable( + mediaPlayers: ConcurrentMap, + methodChannel: MethodChannel, + handler: Handler, + updateCallback: IUpdateCallback, + ) : Runnable { + private val mediaPlayers = WeakReference(mediaPlayers) + private val methodChannel = WeakReference(methodChannel) + private val handler = WeakReference(handler) + private val updateCallback = WeakReference(updateCallback) + + override fun run() { + val mediaPlayers = mediaPlayers.get() + val channel = methodChannel.get() + val handler = handler.get() + val updateCallback = updateCallback.get() + if (mediaPlayers == null || channel == null || handler == null || updateCallback == null) { + updateCallback?.stopUpdates() + return + } + var isAnyPlaying = false + for (player in mediaPlayers.values) { + if (!player.isActuallyPlaying()) { + continue + } + isAnyPlaying = true + val time = player.getCurrentPosition() + player.eventHandler.success("audio.onCurrentPosition", hashMapOf("value" to (time ?: 0))) + } + if (isAnyPlaying) { + handler.postDelayed(this, 200) + } else { + updateCallback.stopUpdates() + } + } + } +} + +private interface IUpdateCallback { + fun stopUpdates() + fun startUpdates() +} + +private inline fun > MethodCall.enumArgument(name: String): T? { + val enumName = argument(name) ?: return null + return enumValueOf(enumName.split('.').last().toConstantCase()) +} + +fun String.toConstantCase(): String { + return replace(Regex("(.)(\\p{Upper})"), "$1_$2").replace(Regex("(.) (.)"), "$1_$2").uppercase() +} + +private fun MethodCall.audioContext(): AudioContextAndroid { + return AudioContextAndroid( + isSpeakerphoneOn = argument("isSpeakerphoneOn") ?: error("isSpeakerphoneOn is required"), + stayAwake = argument("stayAwake") ?: error("stayAwake is required"), + contentType = argument("contentType") ?: error("contentType is required"), + usageType = argument("usageType") ?: error("usageType is required"), + audioFocus = argument("audioFocus") ?: error("audioFocus is required"), + audioMode = argument("audioMode") ?: error("audioMode is required"), + ) +} + +class EventHandler(private val eventChannel: EventChannel) : EventChannel.StreamHandler { + private var eventSink: EventChannel.EventSink? = null + + init { + eventChannel.setStreamHandler(this) + } + + override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { + eventSink = events + } + + override fun onCancel(arguments: Any?) { + eventSink = null + } + + fun success(method: String, arguments: Map = HashMap()) { + eventSink?.success(arguments + Pair("event", method)) + } + + fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) { + eventSink?.error(errorCode, errorMessage, errorDetails) + } + + fun dispose() { + eventSink?.let { + it.endOfStream() + onCancel(null) + } + eventChannel.setStreamHandler(null) + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/ByteDataSource.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/ByteDataSource.kt new file mode 100644 index 000000000..1a59f4e53 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/ByteDataSource.kt @@ -0,0 +1,35 @@ +package xyz.luan.audioplayers + +import android.media.MediaDataSource +import android.os.Build +import androidx.annotation.RequiresApi + +@RequiresApi(Build.VERSION_CODES.M) +class ByteDataSource( + private val data: ByteArray, +) : MediaDataSource() { + @Synchronized + override fun getSize(): Long = data.size.toLong() + + @Synchronized + override fun close() = Unit + + @Synchronized + override fun readAt(position: Long, buffer: ByteArray, offset: Int, size: Int): Int { + if (position >= data.size) { + return -1 + } + + val remainingSize = computeRemainingSize(size, position) + System.arraycopy(data, position.toInt(), buffer, offset, remainingSize) + return remainingSize + } + + private fun computeRemainingSize(size: Int, position: Long): Int { + var remainingSize = size.toLong() + if (position + remainingSize > data.size) { + remainingSize -= position + remainingSize - data.size + } + return remainingSize.toInt() + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/PlayerMode.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/PlayerMode.kt new file mode 100644 index 000000000..d2a249e29 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/PlayerMode.kt @@ -0,0 +1,5 @@ +package xyz.luan.audioplayers + +enum class PlayerMode { + MEDIA_PLAYER, LOW_LATENCY +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/ReleaseMode.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/ReleaseMode.kt new file mode 100644 index 000000000..cadb54b37 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/ReleaseMode.kt @@ -0,0 +1,5 @@ +package xyz.luan.audioplayers + +enum class ReleaseMode { + RELEASE, LOOP, STOP +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/FocusManager.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/FocusManager.kt new file mode 100644 index 000000000..0b8e5115e --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/FocusManager.kt @@ -0,0 +1,75 @@ +package xyz.luan.audioplayers.player + +import android.media.AudioFocusRequest +import android.media.AudioManager +import android.os.Build +import androidx.annotation.RequiresApi +import xyz.luan.audioplayers.AudioContextAndroid + +class FocusManager( + private val player: WrappedPlayer, +) { + private var audioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null + private var audioFocusRequest: AudioFocusRequest? = null + + private val context: AudioContextAndroid + get() = player.context + + private val audioManager: AudioManager + get() = player.audioManager + + fun maybeRequestAudioFocus(andThen: () -> Unit) { + if (context.audioFocus == AudioManager.AUDIOFOCUS_NONE) { + andThen() + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + newRequestAudioFocus(andThen) + } else { + @Suppress("DEPRECATION") + oldRequestAudioFocus(andThen) + } + } + + fun handleStop() { + if (context.audioFocus != AudioManager.AUDIOFOCUS_NONE) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + audioFocusRequest?.let { audioManager.abandonAudioFocusRequest(it) } + } else { + @Suppress("DEPRECATION") + audioManager.abandonAudioFocus(audioFocusChangeListener) + } + } + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun newRequestAudioFocus(andThen: () -> Unit) { + val audioFocus = context.audioFocus + + val audioFocusRequest = AudioFocusRequest.Builder(audioFocus) + .setAudioAttributes(context.buildAttributes()) + .setOnAudioFocusChangeListener { handleFocusResult(it, andThen) } + .build() + this.audioFocusRequest = audioFocusRequest + + val result = audioManager.requestAudioFocus(audioFocusRequest) + handleFocusResult(result, andThen) + } + + @Deprecated("Use requestAudioFocus instead") + private fun oldRequestAudioFocus(andThen: () -> Unit) { + val audioFocus = context.audioFocus + audioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { handleFocusResult(it, andThen) } + @Suppress("DEPRECATION") + val result = audioManager.requestAudioFocus( + audioFocusChangeListener, + AudioManager.STREAM_MUSIC, + audioFocus, + ) + handleFocusResult(result, andThen) + } + + private fun handleFocusResult(result: Int, andThen: () -> Unit) { + if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { + andThen() + } + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/MediaPlayerPlayer.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/MediaPlayerPlayer.kt new file mode 100644 index 000000000..9cff7e389 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/MediaPlayerPlayer.kt @@ -0,0 +1,103 @@ +package xyz.luan.audioplayers.player + +import android.media.MediaPlayer +import android.os.Build +import android.os.PowerManager +import xyz.luan.audioplayers.AudioContextAndroid +import xyz.luan.audioplayers.source.Source + +class MediaPlayerPlayer( + private val wrappedPlayer: WrappedPlayer, +) : Player { + private val mediaPlayer = createMediaPlayer(wrappedPlayer) + + private fun createMediaPlayer(wrappedPlayer: WrappedPlayer): MediaPlayer { + val mediaPlayer = MediaPlayer().apply { + setOnPreparedListener { wrappedPlayer.onPrepared() } + setOnCompletionListener { wrappedPlayer.onCompletion() } + setOnSeekCompleteListener { wrappedPlayer.onSeekComplete() } + setOnErrorListener { _, what, extra -> wrappedPlayer.onError(what, extra) } + setOnBufferingUpdateListener { _, percent -> wrappedPlayer.onBuffering(percent) } + } + wrappedPlayer.context.setAttributesOnPlayer(mediaPlayer) + return mediaPlayer + } + + override fun getDuration(): Int? { + // media player returns -1 if the duration is unknown + return mediaPlayer.duration.takeUnless { it == -1 } + } + + override fun getCurrentPosition(): Int { + return mediaPlayer.currentPosition + } + + override fun isActuallyPlaying(): Boolean { + return mediaPlayer.isPlaying + } + + override fun setVolume(leftVolume: Float, rightVolume: Float) { + mediaPlayer.setVolume(leftVolume, rightVolume) + } + + override fun setRate(rate: Float) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + mediaPlayer.playbackParams = mediaPlayer.playbackParams.setSpeed(rate) + } else if (rate == 1.0f) { + mediaPlayer.start() + } else { + error("Changing the playback rate is only available for Android M/23+ or using LOW_LATENCY mode.") + } + } + + override fun setSource(source: Source) { + reset() + source.setForMediaPlayer(mediaPlayer) + } + + override fun setLooping(looping: Boolean) { + mediaPlayer.isLooping = looping + } + + override fun start() { + // Setting playback rate instead of mediaPlayer.start(). + setRate(wrappedPlayer.rate) + } + + override fun pause() { + mediaPlayer.pause() + } + + override fun stop() { + mediaPlayer.stop() + } + + override fun release() { + mediaPlayer.reset() + mediaPlayer.release() + } + + override fun seekTo(position: Int) { + mediaPlayer.seekTo(position) + } + + override fun updateContext(context: AudioContextAndroid) { + context.setAttributesOnPlayer(mediaPlayer) + if (context.stayAwake) { + mediaPlayer.setWakeMode(wrappedPlayer.applicationContext, PowerManager.PARTIAL_WAKE_LOCK) + } + } + + override fun prepare() { + mediaPlayer.prepareAsync() + } + + override fun reset() { + mediaPlayer.reset() + } + + override fun isLiveStream(): Boolean { + val duration = getDuration() + return duration == null || duration == 0 + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/Player.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/Player.kt new file mode 100644 index 000000000..db7df08b0 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/Player.kt @@ -0,0 +1,26 @@ +package xyz.luan.audioplayers.player + +import xyz.luan.audioplayers.AudioContextAndroid +import xyz.luan.audioplayers.source.Source + +interface Player { + fun getDuration(): Int? + fun getCurrentPosition(): Int? + fun isActuallyPlaying(): Boolean + fun isLiveStream(): Boolean + + fun start() + fun pause() + fun stop() + fun seekTo(position: Int) + fun release() + + fun setVolume(leftVolume: Float, rightVolume: Float) + fun setRate(rate: Float) + fun setLooping(looping: Boolean) + fun updateContext(context: AudioContextAndroid) + fun setSource(source: Source) + + fun prepare() + fun reset() +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/SoundPoolPlayer.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/SoundPoolPlayer.kt new file mode 100644 index 000000000..4205bef6b --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/SoundPoolPlayer.kt @@ -0,0 +1,296 @@ +package xyz.luan.audioplayers.player + +import android.media.AudioAttributes +import android.media.AudioManager +import android.media.SoundPool +import android.os.Build +import xyz.luan.audioplayers.AudioContextAndroid +import xyz.luan.audioplayers.AudioplayersPlugin +import xyz.luan.audioplayers.source.Source +import xyz.luan.audioplayers.source.UrlSource +import java.util.Collections.synchronizedMap + +/** Value should not exceed 32 */ +// TODO(luan): make this configurable +private const val MAX_STREAMS = 32 + +class SoundPoolPlayer( + val wrappedPlayer: WrappedPlayer, + private val soundPoolManager: SoundPoolManager, +) : Player { + + /** The id of the sound of source which will be played */ + var soundId: Int? = null + + /** The id of the stream / player */ + private var streamId: Int? = null + + private var audioContext = wrappedPlayer.context + set(value) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // AudioAttributes are compared by its property values. + if (field.buildAttributes() != value.buildAttributes()) { + release() + soundPoolManager.createSoundPoolWrapper(MAX_STREAMS, value) + soundPoolWrapper = soundPoolManager.getSoundPoolWrapper(value) + ?: error("Could not create SoundPool $value") + } + } + field = value + } + + private var soundPoolWrapper: SoundPoolWrapper + + private val soundPool: SoundPool + get() = soundPoolWrapper.soundPool + + init { + soundPoolManager.createSoundPoolWrapper(MAX_STREAMS, audioContext) + soundPoolWrapper = soundPoolManager.getSoundPoolWrapper(audioContext) + ?: error("Could not create SoundPool $audioContext") + } + + override fun stop() { + streamId?.let { + soundPool.stop(it) + streamId = null + } + } + + override fun release() { + stop() + val soundId = this.soundId ?: return + val urlSource = this.urlSource ?: return + + synchronized(soundPoolWrapper.urlToPlayers) { + val playersForSoundId = soundPoolWrapper.urlToPlayers[urlSource] ?: return + if (playersForSoundId.singleOrNull() === this) { + soundPoolWrapper.urlToPlayers.remove(urlSource) + soundPool.unload(soundId) + soundPoolWrapper.soundIdToPlayer.remove(soundId) + wrappedPlayer.handleLog("unloaded soundId $soundId") + } else { + // This is not the last player using the soundId, just remove it from the list. + playersForSoundId.remove(this) + } + this.soundId = null + this.urlSource = null + } + } + + override fun pause() { + streamId?.let { soundPool.pause(it) } + } + + override fun updateContext(context: AudioContextAndroid) { + audioContext = context + } + + override fun setSource(source: Source) { + source.setForSoundPool(this) + } + + var urlSource: UrlSource? = null + set(value) { + if (value != null) { + synchronized(soundPoolWrapper.urlToPlayers) { + val urlPlayers = soundPoolWrapper.urlToPlayers.getOrPut(value) { mutableListOf() } + val originalPlayer = urlPlayers.firstOrNull() + + if (originalPlayer != null) { + // Sound has already been loaded - reuse the soundId. + val prepared = originalPlayer.wrappedPlayer.prepared + wrappedPlayer.prepared = prepared + soundId = originalPlayer.soundId + wrappedPlayer.handleLog("Reusing soundId $soundId for $value is prepared=$prepared $this") + } else { + // First one for this URL - load it. + val start = System.currentTimeMillis() + + wrappedPlayer.prepared = false + wrappedPlayer.handleLog("Fetching actual URL for $value") + val actualUrl = value.getAudioPathForSoundPool() + wrappedPlayer.handleLog("Now loading $actualUrl") + val intSoundId = soundPool.load(actualUrl, 1) + soundPoolWrapper.soundIdToPlayer[intSoundId] = this + soundId = intSoundId + + wrappedPlayer.handleLog( + "time to call load() for $value: ${System.currentTimeMillis() - start} player=$this", + ) + } + urlPlayers.add(this) + } + } + field = value + } + + override fun setVolume(leftVolume: Float, rightVolume: Float) { + streamId?.let { soundPool.setVolume(it, leftVolume, rightVolume) } + } + + override fun setRate(rate: Float) { + streamId?.let { soundPool.setRate(it, rate) } + } + + override fun setLooping(looping: Boolean) { + streamId?.let { soundPool.setLoop(it, looping.loopModeInteger()) } + } + + // Cannot get duration for Sound Pool + override fun getDuration() = null + + // Cannot get current position for Sound Pool + override fun getCurrentPosition() = null + + override fun isActuallyPlaying() = false + + override fun seekTo(position: Int) { + if (position == 0) { + streamId?.let { + stop() + if (wrappedPlayer.playing) { + soundPool.resume(it) + } + } + } else { + unsupportedOperation("seek") + } + } + + override fun start() { + val streamId = streamId + val soundId = soundId + + if (streamId != null) { + soundPool.resume(streamId) + } else if (soundId != null) { + this.streamId = soundPool.play( + soundId, + wrappedPlayer.volume, + wrappedPlayer.volume, + 0, + wrappedPlayer.isLooping.loopModeInteger(), + wrappedPlayer.rate, + ) + } + } + + override fun prepare() { + // sound pool automatically prepares when source URL is set + } + + override fun reset() { + // TODO(luan): what do I do here? + } + + override fun isLiveStream() = false + + /** Integer representation of the loop mode used by Android */ + private fun Boolean.loopModeInteger(): Int = if (this) -1 else 0 + + private fun unsupportedOperation(message: String): Nothing { + throw UnsupportedOperationException("LOW_LATENCY mode does not support: $message") + } +} + +class SoundPoolManager( + private val ref: AudioplayersPlugin, +) { + + // Only needed for legacy apps with SDK < 21 + private var legacySoundPoolWrapper: SoundPoolWrapper? = null + + /** + * Lazy store one [SoundPoolWrapper] for each [AudioAttributes] configuration. + * [AudioAttributes] are compared by its property values, so it can be used as key. + */ + private val soundPoolWrappers = HashMap() + + /** + * Create a SoundPoolWrapper with the given [maxStreams] and the according [audioContext] and save it to be + * globally accessible for every player. + * + * @param maxStreams the maximum number of simultaneous streams for this + * SoundPool object, see [SoundPool.Builder.setMaxStreams] + */ + fun createSoundPoolWrapper(maxStreams: Int, audioContext: AudioContextAndroid) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + val attrs = audioContext.buildAttributes() + if (!soundPoolWrappers.containsKey(attrs)) { + val soundPool = SoundPool.Builder() + .setAudioAttributes(attrs) + .setMaxStreams(maxStreams) + .build() + ref.handleGlobalLog("Create SoundPool with $attrs") + val soundPoolWrapper = SoundPoolWrapper(soundPool) + soundPoolWrapper.soundPool.setOnLoadCompleteListener { _, sampleId, _ -> + ref.handleGlobalLog("Loaded $sampleId") + val loadingPlayer = soundPoolWrapper.soundIdToPlayer[sampleId] + val urlSource = loadingPlayer?.urlSource + if (urlSource != null) { + soundPoolWrapper.soundIdToPlayer.remove(loadingPlayer.soundId) + // Now mark all players using this sound as not loading and start them if necessary + synchronized(soundPoolWrapper.urlToPlayers) { + val urlPlayers = soundPoolWrapper.urlToPlayers[urlSource] ?: listOf() + for (player in urlPlayers) { + player.wrappedPlayer.handleLog("Marking $player as loaded") + player.wrappedPlayer.prepared = true + if (player.wrappedPlayer.playing) { + player.wrappedPlayer.handleLog("Delayed start of $player") + player.start() + } + } + } + } + } + soundPoolWrappers[attrs] = soundPoolWrapper + } + } else if (legacySoundPoolWrapper == null) { + @Suppress("DEPRECATION") + val soundPool = SoundPool(maxStreams, AudioManager.STREAM_MUSIC, 0) + ref.handleGlobalLog("Create legacy SoundPool") + legacySoundPoolWrapper = SoundPoolWrapper(soundPool) + } + } + + /** + * Get the [SoundPoolWrapper] with the given [audioContext]. + */ + fun getSoundPoolWrapper(audioContext: AudioContextAndroid): SoundPoolWrapper? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + val attrs = audioContext.buildAttributes() + soundPoolWrappers[attrs] + } else { + legacySoundPoolWrapper + } + } + + fun dispose() { + for (soundPoolEntry in soundPoolWrappers) { + soundPoolEntry.value.dispose() + } + soundPoolWrappers.clear() + } +} + +class SoundPoolWrapper(val soundPool: SoundPool) { + + /** For the onLoadComplete listener, track which sound id is associated with which player. An entry only exists until + * it has been loaded. + */ + val soundIdToPlayer: MutableMap = synchronizedMap(mutableMapOf()) + + /** This is to keep track of the players which share the same sound id, referenced by url. When a player release()s, it + * is removed from the associated player list. The last player to be removed actually unloads() the sound id and then + * the url is removed from this map. + */ + val urlToPlayers: MutableMap> = + synchronizedMap(mutableMapOf>()) + + fun dispose() { + soundPool.release() + soundIdToPlayer.clear() + urlToPlayers.clear() + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/WrappedPlayer.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/WrappedPlayer.kt new file mode 100644 index 000000000..183ea2923 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/player/WrappedPlayer.kt @@ -0,0 +1,384 @@ +package xyz.luan.audioplayers.player + +import android.content.Context +import android.media.AudioManager +import android.media.MediaPlayer +import xyz.luan.audioplayers.AudioContextAndroid +import xyz.luan.audioplayers.AudioplayersPlugin +import xyz.luan.audioplayers.EventHandler +import xyz.luan.audioplayers.PlayerMode +import xyz.luan.audioplayers.PlayerMode.LOW_LATENCY +import xyz.luan.audioplayers.PlayerMode.MEDIA_PLAYER +import xyz.luan.audioplayers.ReleaseMode +import xyz.luan.audioplayers.source.Source +import kotlin.math.min + +// For some reason this cannot be accessed from MediaPlayer.MEDIA_ERROR_SYSTEM +private const val MEDIA_ERROR_SYSTEM = -2147483648 + +class WrappedPlayer internal constructor( + private val ref: AudioplayersPlugin, + val eventHandler: EventHandler, + var context: AudioContextAndroid, + private val soundPoolManager: SoundPoolManager, +) { + private var player: Player? = null + + var source: Source? = null + set(value) { + if (field != value) { + if (value != null) { + val player = getOrCreatePlayer() + player.setSource(value) + player.configAndPrepare() + } else { + released = true + prepared = false + playing = false + player?.release() + } + field = value + } else { + ref.handlePrepared(this, true) + } + } + + var volume = 1.0f + set(value) { + if (field != value) { + field = value + if (!released) { + player?.setVolumeAndBalance(value, balance) + } + } + } + + var balance = 0.0f + set(value) { + if (field != value) { + field = value + if (!released) { + player?.setVolumeAndBalance(volume, value) + } + } + } + + var rate = 1.0f + set(value) { + if (field != value) { + field = value + if (playing) { + player?.setRate(value) + } + } + } + + var releaseMode = ReleaseMode.RELEASE + set(value) { + if (field != value) { + field = value + if (!released) { + player?.setLooping(isLooping) + } + } + } + + val isLooping: Boolean + get() = releaseMode == ReleaseMode.LOOP + + var playerMode: PlayerMode = MEDIA_PLAYER + set(value) { + if (field != value) { + field = value + + // if the player exists, we need to re-create it from scratch; + // this will probably cause music to pause for a second + player?.let { + shouldSeekTo = maybeGetCurrentPosition() + prepared = false + it.release() + } + initPlayer() + } + } + + var released = true + + var prepared: Boolean = false + set(value) { + if (field != value) { + field = value + ref.handlePrepared(this, value) + } + } + + var playing = false + var shouldSeekTo = -1 + + private val focusManager = FocusManager(this) + + private fun maybeGetCurrentPosition(): Int { + // for Sound Pool, we can't get current position, so we just start over + return runCatching { player?.getCurrentPosition().takeUnless { it == 0 } }.getOrNull() ?: -1 + } + + private fun getOrCreatePlayer(): Player { + val currentPlayer = player + return if (released || currentPlayer == null) { + createPlayer().also { + player = it + released = false + } + } else if (prepared) { + currentPlayer.also { + it.reset() + prepared = false + } + } else { + currentPlayer + } + } + + fun updateAudioContext(audioContext: AudioContextAndroid) { + if (context == audioContext) { + return + } + if (context.audioFocus != AudioManager.AUDIOFOCUS_NONE && + audioContext.audioFocus == AudioManager.AUDIOFOCUS_NONE + ) { + focusManager.handleStop() + } + this.context = audioContext.copy() + + // AudioManager values are set globally + audioManager.mode = context.audioMode + audioManager.isSpeakerphoneOn = context.isSpeakerphoneOn + + player?.let { p -> + p.stop() + prepared = false + // Context is only applied, once the player.reset() was called + p.updateContext(context) + source?.let { + p.setSource(it) + p.configAndPrepare() + } + } + } + + // Getters + + /** + * Returns the duration of the media in milliseconds, if available. + */ + fun getDuration(): Int? { + return if (prepared) player?.getDuration() else null + } + + /** + * Returns the current position of the playback in milliseconds, if available. + */ + fun getCurrentPosition(): Int? { + return if (prepared) player?.getCurrentPosition() else null + } + + fun isActuallyPlaying(): Boolean { + return playing && prepared && player?.isActuallyPlaying() == true + } + + val applicationContext: Context + get() = ref.getApplicationContext() + + val audioManager: AudioManager + get() = ref.getAudioManager() + + /** + * Playback handling methods + */ + fun play() { + focusManager.maybeRequestAudioFocus(andThen = ::actuallyPlay) + } + + private fun actuallyPlay() { + if (!playing && !released) { + val currentPlayer = player + playing = true + if (currentPlayer == null) { + initPlayer() + } else if (prepared) { + currentPlayer.start() + ref.handleIsPlaying() + } + } + } + + fun stop() { + focusManager.handleStop() + if (released) { + return + } + if (releaseMode != ReleaseMode.RELEASE) { + pause() + if (prepared) { + if (player?.isLiveStream() == true) { + player?.stop() + prepared = false + player?.prepare() + } else { + // MediaPlayer does not allow to call player.seekTo after calling player.stop + seek(0) + } + } + } else { + release() + } + } + + fun release() { + focusManager.handleStop() + if (released) { + return + } + if (playing) { + player?.stop() + } + + // Setting source to null will reset released, prepared and playing + // and also calls player.release() + source = null + player = null + } + + fun pause() { + if (playing) { + playing = false + if (prepared) { + player?.pause() + } + } + } + + // seek operations cannot be called until after + // the player is ready. + fun seek(position: Int) { + shouldSeekTo = if (prepared && player?.isLiveStream() != true) { + player?.seekTo(position) + -1 + } else { + position + } + } + + /** + * Player callbacks + */ + fun onPrepared() { + prepared = true + ref.handleDuration(this) + if (playing) { + player?.start() + ref.handleIsPlaying() + } + if (shouldSeekTo >= 0 && player?.isLiveStream() != true) { + player?.seekTo(shouldSeekTo) + } + } + + fun onCompletion() { + if (releaseMode != ReleaseMode.LOOP) { + stop() + } + ref.handleComplete(this) + } + + @Suppress("UNUSED_PARAMETER") + fun onBuffering(percent: Int) { + // TODO(luan): expose this as a stream + } + + fun onSeekComplete() { + ref.handleSeekComplete(this) + } + + fun handleLog(message: String) { + ref.handleLog(this, message) + } + + fun handleError(errorCode: String?, errorMessage: String?, errorDetails: Any?) { + ref.handleError(this, errorCode, errorMessage, errorDetails) + } + + fun onError(what: Int, extra: Int): Boolean { + val whatMsg = if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) { + "MEDIA_ERROR_SERVER_DIED" + } else { + "MEDIA_ERROR_UNKNOWN {what:$what}" + } + val extraMsg = when (extra) { + MEDIA_ERROR_SYSTEM -> "MEDIA_ERROR_SYSTEM" + MediaPlayer.MEDIA_ERROR_IO -> "MEDIA_ERROR_IO" + MediaPlayer.MEDIA_ERROR_MALFORMED -> "MEDIA_ERROR_MALFORMED" + MediaPlayer.MEDIA_ERROR_UNSUPPORTED -> "MEDIA_ERROR_UNSUPPORTED" + MediaPlayer.MEDIA_ERROR_TIMED_OUT -> "MEDIA_ERROR_TIMED_OUT" + else -> "MEDIA_ERROR_UNKNOWN {extra:$extra}" + } + if (!prepared && extraMsg == "MEDIA_ERROR_SYSTEM") { + handleError( + "AndroidAudioError", + "Failed to set source. For troubleshooting, see: " + + "https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md", + "$whatMsg, $extraMsg", + ) + } else { + // When an error occurs, reset player to not [prepared]. + // Then no functions will be called, which end up in an illegal player state. + prepared = false + handleError("AndroidAudioError", whatMsg, extraMsg) + } + return false + } + + /** + * Internal logic. Private methods + */ + + /** + * Create new player + */ + private fun createPlayer(): Player { + return when (playerMode) { + MEDIA_PLAYER -> MediaPlayerPlayer(this) + LOW_LATENCY -> SoundPoolPlayer(this, soundPoolManager) + } + } + + /** + * Create new player, assign and configure source + */ + private fun initPlayer() { + val player = createPlayer() + // Need to set player before calling prepare, as onPrepared may is called before player is assigned + this.player = player + source?.let { + player.setSource(it) + player.configAndPrepare() + } + } + + private fun Player.configAndPrepare() { + setVolumeAndBalance(volume, balance) + setLooping(isLooping) + prepare() + } + + private fun Player.setVolumeAndBalance(volume: Float, balance: Float) { + val leftVolume = min(1f, 1f - balance) * volume + val rightVolume = min(1f, 1f + balance) * volume + setVolume(leftVolume, rightVolume) + } + + fun dispose() { + release() + eventHandler.dispose() + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/BytesSource.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/BytesSource.kt new file mode 100644 index 000000000..eec5bd648 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/BytesSource.kt @@ -0,0 +1,22 @@ +package xyz.luan.audioplayers.source + +import android.media.MediaPlayer +import android.os.Build +import androidx.annotation.RequiresApi +import xyz.luan.audioplayers.ByteDataSource +import xyz.luan.audioplayers.player.SoundPoolPlayer + +@RequiresApi(Build.VERSION_CODES.M) +data class BytesSource( + val dataSource: ByteDataSource, +) : Source { + constructor(bytes: ByteArray) : this(ByteDataSource(bytes)) + + override fun setForMediaPlayer(mediaPlayer: MediaPlayer) { + mediaPlayer.setDataSource(dataSource) + } + + override fun setForSoundPool(soundPoolPlayer: SoundPoolPlayer) { + error("Bytes sources are not supported on LOW_LATENCY mode yet.") + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/Source.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/Source.kt new file mode 100644 index 000000000..8d410bed7 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/Source.kt @@ -0,0 +1,10 @@ +package xyz.luan.audioplayers.source + +import android.media.MediaPlayer +import xyz.luan.audioplayers.player.SoundPoolPlayer + +// TODO(luan) replace this indirection with a sealed interface once we have that option! +interface Source { + fun setForMediaPlayer(mediaPlayer: MediaPlayer) + fun setForSoundPool(soundPoolPlayer: SoundPoolPlayer) +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/UrlSource.kt b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/UrlSource.kt new file mode 100644 index 000000000..ad371e872 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/main/kotlin/xyz/luan/audioplayers/source/UrlSource.kt @@ -0,0 +1,53 @@ +package xyz.luan.audioplayers.source + +import android.media.MediaPlayer +import xyz.luan.audioplayers.player.SoundPoolPlayer +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.FileOutputStream +import java.net.URI +import java.net.URL + +data class UrlSource( + val url: String, + val isLocal: Boolean, +) : Source { + override fun setForMediaPlayer(mediaPlayer: MediaPlayer) { + mediaPlayer.setDataSource(url) + } + + override fun setForSoundPool(soundPoolPlayer: SoundPoolPlayer) { + soundPoolPlayer.release() + soundPoolPlayer.urlSource = this + } + + fun getAudioPathForSoundPool(): String { + if (isLocal) { + return url.removePrefix("file://") + } + + return loadTempFileFromNetwork().absolutePath + } + + private fun loadTempFileFromNetwork(): File { + val bytes = downloadUrl(URI.create(url).toURL()) + val tempFile = File.createTempFile("sound", "") + FileOutputStream(tempFile).use { + it.write(bytes) + tempFile.deleteOnExit() + } + return tempFile + } + + private fun downloadUrl(url: URL): ByteArray { + val outputStream = ByteArrayOutputStream() + url.openStream().use { stream -> + val chunk = ByteArray(4096) + while (true) { + val bytesRead = stream.read(chunk).takeIf { it > 0 } ?: break + outputStream.write(chunk, 0, bytesRead) + } + } + return outputStream.toByteArray() + } +} diff --git a/third_party/pub_patches/audioplayers_android/android/src/test/kotlin/xyz/luan/audioplayers/ToConstantCaseTest.kt b/third_party/pub_patches/audioplayers_android/android/src/test/kotlin/xyz/luan/audioplayers/ToConstantCaseTest.kt new file mode 100644 index 000000000..9c6cb85f5 --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/android/src/test/kotlin/xyz/luan/audioplayers/ToConstantCaseTest.kt @@ -0,0 +1,18 @@ +package xyz.luan.audioplayers + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ToConstantCaseTest { + @Test + fun `convert from sentence case`() { + assertThat("foo".toConstantCase()).isEqualTo("FOO") + assertThat("foo bar".toConstantCase()).isEqualTo("FOO_BAR") + } + + @Test + fun `convert from camelCase`() { + assertThat("foo".toConstantCase()).isEqualTo("FOO") + assertThat("fooBar".toConstantCase()).isEqualTo("FOO_BAR") + } +} diff --git a/third_party/pub_patches/audioplayers_android/pubspec.yaml b/third_party/pub_patches/audioplayers_android/pubspec.yaml new file mode 100644 index 000000000..b4666b6ca --- /dev/null +++ b/third_party/pub_patches/audioplayers_android/pubspec.yaml @@ -0,0 +1,29 @@ +name: audioplayers_android +description: Android implementation of audioplayers, a Flutter plugin to play multiple audio files simultaneously +version: 4.0.3 +homepage: https://github.com/bluefireteam/audioplayers +repository: https://github.com/bluefireteam/audioplayers/tree/master/packages/audioplayers_android + +flutter: + plugin: + implements: audioplayers + platforms: + android: + package: xyz.luan.audioplayers + pluginClass: AudioplayersPlugin + +dependencies: + audioplayers_platform_interface: ^6.1.0 + flutter: + sdk: flutter + +dev_dependencies: + dartdoc: ^6.1.5 + flame_lint: ^1.0.0 + flutter_test: + sdk: flutter + +environment: + sdk: '>=3.0.0 <4.0.0' + flutter: '>=3.10.0' + diff --git a/third_party/pub_patches/fl_location/CHANGELOG.md b/third_party/pub_patches/fl_location/CHANGELOG.md new file mode 100644 index 000000000..cfe836746 --- /dev/null +++ b/third_party/pub_patches/fl_location/CHANGELOG.md @@ -0,0 +1,44 @@ +## 2.1.1 + +* [**FIX**] Fix IllegalStateException [#12](https://github.com/Dev-hwang/flutter_location/issues/12) + +## 2.1.0 + +* [**FEAT**] Add ability to get location in the background [#10](https://github.com/Dev-hwang/flutter_location/issues/10) +* [**FIX**] Fix ConcurrentModificationException [#13](https://github.com/Dev-hwang/flutter_location/issues/13) +* [**FIX**] Fix location update channel close issue [#14](https://github.com/Dev-hwang/flutter_location/issues/14) + +## 2.0.0 + +* [**CHORE**] Upgrade minimum Flutter version to 3.0.0 +* [**CHORE**] Upgrade dependencies + +## 1.2.2 + +* [[#4](https://github.com/Dev-hwang/flutter_location/issues/4)] Fix onRequestPermissionsResult implement issue. + +## 1.2.1 + +* Upgrade dependencies. +* Downgrade Android minSdkVersion to 21. + +## 1.2.0 + +* Upgrade dependencies. +* Added LocationUtils class which implements `distanceBetween` and `bearingBetween` functions. +* Bump Android minSdkVersion to 23. +* Bump Android compileSdkVersion to 31. + +## 1.1.0 + +* Now this plugin is also available on the web. + +## 1.0.1 + +* Upgrade `fl_location_platform_interface: ^1.0.1` +* Fixed invalid homepage URL. +* Fixed an issue where `getLocation` and `getLocationStream` functions could not be called at the same time. + +## 1.0.0 + +* Initial release. diff --git a/third_party/pub_patches/fl_location/LICENSE b/third_party/pub_patches/fl_location/LICENSE new file mode 100644 index 000000000..0bc6bc8b8 --- /dev/null +++ b/third_party/pub_patches/fl_location/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Dev-hwang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/pub_patches/fl_location/README.md b/third_party/pub_patches/fl_location/README.md new file mode 100644 index 000000000..cabe3672f --- /dev/null +++ b/third_party/pub_patches/fl_location/README.md @@ -0,0 +1,217 @@ +# fl_location + +A plugin that can access the location services of each platform and collect device location data. + +## Platform + +- [x] Android +- [x] iOS +- [x] Web + +## Features + +* Can request location permission. +* Can get the current location of the device. +* Can check whether location services are enabled. +* Can subscribe to `LocationStream` to collect location data in real time. +* Can subscribe to `LocationServicesStatusStream` to listen location services status changes in real time. + +## Getting started + +To use this plugin, add `fl_location` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/). For example: + +```yaml +dependencies: + fl_location: ^2.1.1 +``` + +After adding the `fl_location` plugin to the flutter project, we need to specify the platform-specific permissions for this plugin to work properly. + +### :baby_chick: Android + +Since this plugin works based on location, we need to add the following permission to the `AndroidManifest.xml` file. Open the `AndroidManifest.xml` file and specify it between the `` and `` tags. + +``` + + +``` + +If you want to get the location in the background, add the following permission. If your project supports Android 10, be sure to add the `ACCESS_BACKGROUND_LOCATION` permission. + +``` + +``` + +### :baby_chick: iOS + +Like the Android platform, this plugin works based on location, we need to add the following description. Open the `ios/Runner/Info.plist` file and specify it inside the `` tag. + +``` +NSLocationWhenInUseUsageDescription +Used to collect location data. +``` + +If you want to get the location in the background, add the following description. + +``` +NSLocationAlwaysAndWhenInUseUsageDescription +Used to collect location data in the background. +NSLocationAlwaysUsageDescription +Used to collect location data in the background. +UIBackgroundModes + + fetch + location + +``` + +## How to use + +1. Check whether the location permission is allowed or not, and if not allowed, request the location permission. + +```dart +Future _checkAndRequestPermission({bool? background}) async { + if (!await FlLocation.isLocationServicesEnabled) { + // Location services are disabled. + return false; + } + + var locationPermission = await FlLocation.checkLocationPermission(); + if (locationPermission == LocationPermission.deniedForever) { + // Cannot request runtime permission because location permission is denied forever. + return false; + } else if (locationPermission == LocationPermission.denied) { + // Ask the user for location permission. + locationPermission = await FlLocation.requestLocationPermission(); + if (locationPermission == LocationPermission.denied || + locationPermission == LocationPermission.deniedForever) return false; + } + + // Location permission must always be allowed (LocationPermission.always) + // to collect location data in the background. + if (background == true && + locationPermission == LocationPermission.whileInUse) return false; + + // Location services has been enabled and permission have been granted. + return true; +} +``` + +2. To get the current location, use the `getLocation` function. + +```dart +Future _getLocation() async { + if (await _checkAndRequestPermission()) { + final timeLimit = const Duration(seconds: 10); + await FlLocation.getLocation(timeLimit: timeLimit).then((location) { + print('location: ${location.toJson().toString()}'); + }).onError((error, stackTrace) { + print('error: ${error.toString()}'); + }); + } +} +``` + +3. To collect location data in real time, use the `getLocationStream` function. + +```dart +StreamSubscription? _locationSubscription; + +Future _listenLocationStream() async { + if (await _checkAndRequestPermission()) { + if (_locationSubscription != null) await _cancelLocationSubscription(); + + _locationSubscription = FlLocation.getLocationStream() + .handleError(_handleError) + .listen((event) { + print('location: ${event.toJson().toString()}'); + }); + } +} + +Future _cancelLocationSubscription() async { + await _locationSubscription?.cancel(); + _locationSubscription = null; +} + +void _handleError(dynamic error, StackTrace stackTrace) { + print('error: ${error.toString()}'); +} +``` + +4. To listen location services status changes in real time, use the `getLocationServicesStatusStream` function. + +```dart +StreamSubscription? _locationServicesStatusSubscription; + +Future _listenLocationServicesStatusStream() async { + if (_locationServicesStatusSubscription != null) + await _cancelLocationServicesStatusSubscription(); + + _locationServicesStatusSubscription = + FlLocation.getLocationServicesStatusStream().listen((event) { + print('location services status: $event'); + }); +} + +Future _cancelLocationServicesStatusSubscription() async { + await _locationServicesStatusSubscription?.cancel(); + _locationServicesStatusSubscription = null; +} +``` + +## Models + +### :chicken: Location + +A data class that represents a location model. + +| Field | Description | +|---|---| +| `latitude` | The latitude of the location. | +| `longitude` | The longitude of the location. | +| `accuracy` | The accuracy of the location. | +| `altitude` | The altitude of the location. | +| `heading` | The angle in the direction the device is moving. | +| `speed` | The movement speed of the device. | +| `speedAccuracy` | The accuracy of `speed`. | +| `millisecondsSinceEpoch` | The millisecondsSinceEpoch at which the location update occurred. | +| `timestamp` | The device time at which the location update occurred. | +| `isMock` | Whether the mock location. | + +### :chicken: LocationAccuracy + +An enumeration of location accuracy. + +| Value | Description | +|---|---| +| `powerSave` | The location has an accuracy of 10km on Android and 3km on iOS. | +| `low` | The location has an accuracy of 10km on Android and 1km on iOS. | +| `balanced` | The location has an accuracy of 100m for both Android and iOS. | +| `high` | The location has an accuracy of ~100m on Android and 10m on iOS. | +| `best` | The location has an accuracy of ~100m on Android and ~10m on iOS. | +| `navigation` | The location has an accuracy of ~100m on Android and optimized for navigation on iOS. | + +### :chicken: LocationPermission + +An enumeration of location permission. + +| Value | Description | +|---|---| +| `always` | The app can read location at any time. The app need this permission to read location in the background. | +| `whileInUse` | The location can only be read while using the app. | +| `denied` | The location cannot be read because permission is denied. The app can request runtime permissions again. | +| `deniedForever` | The location cannot be read because permission is denied. The app can no longer request runtime permissions and must grant permissions manually. | + +### :chicken: LocationServicesStatus + +An enumeration of location services status. + +| Value | Description | +|---|---| +| `enabled` | Location services are enabled. | +| `disabled` | Location services are disabled. | + +## Support + +If you find any bugs or issues while using the plugin, please register an issues on [GitHub](https://github.com/Dev-hwang/flutter_location/issues). You can also contact us at . diff --git a/third_party/pub_patches/fl_location/android/build.gradle b/third_party/pub_patches/fl_location/android/build.gradle new file mode 100644 index 000000000..4a1ebc3f3 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/build.gradle @@ -0,0 +1,49 @@ +group 'com.pravera.fl_location' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + namespace "com.pravera.fl_location" + compileSdkVersion 31 + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + defaultConfig { + minSdkVersion 21 + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.google.android.gms:play-services-location:21.0.1' + implementation 'com.google.code.gson:gson:2.10.1' +} diff --git a/third_party/pub_patches/fl_location/android/gradle.properties b/third_party/pub_patches/fl_location/android/gradle.properties new file mode 100644 index 000000000..94adc3a3f --- /dev/null +++ b/third_party/pub_patches/fl_location/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/third_party/pub_patches/fl_location/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/fl_location/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..cb24abda1 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/third_party/pub_patches/fl_location/android/settings.gradle b/third_party/pub_patches/fl_location/android/settings.gradle new file mode 100644 index 000000000..87ef5147e --- /dev/null +++ b/third_party/pub_patches/fl_location/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'fl_location' diff --git a/third_party/pub_patches/fl_location/android/src/main/AndroidManifest.xml b/third_party/pub_patches/fl_location/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..62a4ab70c --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/FlLocationPlugin.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/FlLocationPlugin.kt new file mode 100644 index 000000000..9f4730480 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/FlLocationPlugin.kt @@ -0,0 +1,82 @@ +package com.pravera.fl_location + +import com.pravera.fl_location.service.* +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding + +/** FlLocationPlugin */ +class FlLocationPlugin: FlutterPlugin, ActivityAware, ServiceProvider { + private lateinit var locationPermissionManager: LocationPermissionManager + private lateinit var locationDataProviderManager: LocationDataProviderManager + private lateinit var locationServicesStatusWatcher: LocationServicesStatusWatcher + + private var activityBinding: ActivityPluginBinding? = null + private lateinit var methodCallHandler: MethodCallHandlerImpl + private lateinit var locationStreamHandler: LocationStreamHandlerImpl + private lateinit var locationServicesStatusStreamHandler: LocationServicesStatusStreamHandlerImpl + + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + val applicationContext = binding.applicationContext + val binaryMessenger = binding.binaryMessenger + + locationPermissionManager = LocationPermissionManager() + locationDataProviderManager = LocationDataProviderManager(applicationContext) + locationServicesStatusWatcher = LocationServicesStatusWatcher() + + methodCallHandler = MethodCallHandlerImpl(applicationContext, this) + methodCallHandler.initChannel(binaryMessenger) + locationStreamHandler = LocationStreamHandlerImpl(applicationContext, this) + locationStreamHandler.initChannel(binaryMessenger) + locationServicesStatusStreamHandler = + LocationServicesStatusStreamHandlerImpl(applicationContext, this) + locationServicesStatusStreamHandler.initChannel(binaryMessenger) + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + if (::methodCallHandler.isInitialized) { + methodCallHandler.disposeChannel() + } + if (::locationStreamHandler.isInitialized) { + locationStreamHandler.disposeChannel() + } + if (::locationServicesStatusStreamHandler.isInitialized) { + locationServicesStatusStreamHandler.disposeChannel() + } + locationDataProviderManager.stopAllLocationUpdates() + } + + override fun onAttachedToActivity(binding: ActivityPluginBinding) { + methodCallHandler.setActivity(binding.activity) + locationStreamHandler.setActivity(binding.activity) + locationServicesStatusStreamHandler.setActivity(binding.activity) + locationDataProviderManager.setActivity(binding.activity) + binding.addRequestPermissionsResultListener(locationPermissionManager) + binding.addActivityResultListener(locationDataProviderManager) + activityBinding = binding + } + + override fun onDetachedFromActivityForConfigChanges() { + onDetachedFromActivity() + } + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + onAttachedToActivity(binding) + } + + override fun onDetachedFromActivity() { + activityBinding?.removeRequestPermissionsResultListener(locationPermissionManager) + activityBinding?.removeActivityResultListener(locationDataProviderManager) + activityBinding = null + methodCallHandler.setActivity(null) + locationStreamHandler.setActivity(null) + locationServicesStatusStreamHandler.setActivity(null) + locationDataProviderManager.setActivity(null) + } + + override fun getLocationPermissionManager() = locationPermissionManager + + override fun getLocationDataProviderManager() = locationDataProviderManager + + override fun getLocationServicesStatusWatcher() = locationServicesStatusWatcher +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/FlLocationPluginChannel.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/FlLocationPluginChannel.kt new file mode 100644 index 000000000..d00a3af23 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/FlLocationPluginChannel.kt @@ -0,0 +1,11 @@ +package com.pravera.fl_location + +import android.app.Activity +import io.flutter.plugin.common.BinaryMessenger + +/** FlLocationPluginChannel */ +interface FlLocationPluginChannel { + fun initChannel(messenger: BinaryMessenger) + fun setActivity(activity: Activity?) + fun disposeChannel() +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/LocationServicesStatusStreamHandlerImpl.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/LocationServicesStatusStreamHandlerImpl.kt new file mode 100644 index 000000000..5c10de0d6 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/LocationServicesStatusStreamHandlerImpl.kt @@ -0,0 +1,41 @@ +package com.pravera.fl_location + +import android.app.Activity +import android.content.Context +import com.pravera.fl_location.service.ServiceProvider +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel + +/** LocationServicesStatusStreamHandlerImpl */ +class LocationServicesStatusStreamHandlerImpl( + private val context: Context, + private val serviceProvider: ServiceProvider): + EventChannel.StreamHandler, FlLocationPluginChannel { + + private lateinit var channel: EventChannel + private var activity: Activity? = null + + override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { + serviceProvider.getLocationServicesStatusWatcher() + .start(context, onChanged = { events?.success(it.ordinal) }) + } + + override fun onCancel(arguments: Any?) { + serviceProvider.getLocationServicesStatusWatcher().stop(context) + } + + override fun initChannel(messenger: BinaryMessenger) { + channel = EventChannel(messenger, + "plugins.pravera.com/fl_location/location_services_status") + channel.setStreamHandler(this) + } + + override fun setActivity(activity: Activity?) { + this.activity = activity + } + + override fun disposeChannel() { + if (::channel.isInitialized) + channel.setStreamHandler(null) + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/LocationStreamHandlerImpl.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/LocationStreamHandlerImpl.kt new file mode 100644 index 000000000..3bf1fc126 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/LocationStreamHandlerImpl.kt @@ -0,0 +1,64 @@ +package com.pravera.fl_location + +import android.app.Activity +import android.content.Context +import com.pravera.fl_location.errors.ErrorCodes +import com.pravera.fl_location.models.LocationSettings +import com.pravera.fl_location.service.LocationDataCallback +import com.pravera.fl_location.service.ServiceProvider +import com.pravera.fl_location.utils.ErrorHandleUtils +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel + +/** LocationStreamHandlerImpl */ +class LocationStreamHandlerImpl( + private val context: Context, + private val serviceProvider: ServiceProvider): + EventChannel.StreamHandler, FlLocationPluginChannel { + + private lateinit var channel: EventChannel + private var activity: Activity? = null + private var locationDataProviderHashCode: Int? = null + + override fun onListen(arguments: Any?, events: EventChannel.EventSink) { + val callback = object : LocationDataCallback { + override fun onUpdate(locationJson: String) { + events.success(locationJson) + } + + override fun onError(errorCode: ErrorCodes) { + ErrorHandleUtils.handleStreamError(events, errorCode) + } + } + + val argsMap = arguments as? Map<*, *> + val settings = LocationSettings.fromMap(argsMap) + + locationDataProviderHashCode = serviceProvider + .getLocationDataProviderManager() + .requestLocationUpdates(callback, settings) + } + + override fun onCancel(arguments: Any?) { + if (locationDataProviderHashCode == null) return + + serviceProvider + .getLocationDataProviderManager() + .stopLocationUpdates(locationDataProviderHashCode!!) + } + + override fun initChannel(messenger: BinaryMessenger) { + channel = EventChannel(messenger, "plugins.pravera.com/fl_location/updates") + channel.setStreamHandler(this) + } + + override fun setActivity(activity: Activity?) { + this.activity = activity + } + + override fun disposeChannel() { + if (::channel.isInitialized) { + channel.setStreamHandler(null) + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/MethodCallHandlerImpl.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/MethodCallHandlerImpl.kt new file mode 100644 index 000000000..ef47f565a --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/MethodCallHandlerImpl.kt @@ -0,0 +1,98 @@ +package com.pravera.fl_location + +import android.app.Activity +import android.content.Context +import com.pravera.fl_location.errors.ErrorCodes +import com.pravera.fl_location.models.LocationPermission +import com.pravera.fl_location.models.LocationSettings +import com.pravera.fl_location.service.LocationDataCallback +import com.pravera.fl_location.service.LocationPermissionCallback +import com.pravera.fl_location.service.ServiceProvider +import com.pravera.fl_location.utils.ErrorHandleUtils +import com.pravera.fl_location.utils.LocationServicesUtils +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel + +/** MethodCallHandlerImpl */ +class MethodCallHandlerImpl( + private val context: Context, + private val serviceProvider: ServiceProvider): + MethodChannel.MethodCallHandler, FlLocationPluginChannel { + + private lateinit var channel: MethodChannel + private var activity: Activity? = null + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + val reqMethod = call.method + if (reqMethod.contains("checkLocationPermission") || + reqMethod.contains("requestLocationPermission")) { + if (activity == null) { + ErrorHandleUtils.handleMethodCallError(result, ErrorCodes.ACTIVITY_NOT_ATTACHED) + return + } + } + + when (reqMethod) { + "checkLocationServicesStatus" -> { + val checkResult = LocationServicesUtils.checkLocationServicesStatus(context) + result.success(checkResult.ordinal) + } + "checkLocationPermission" -> { + val checkResult = serviceProvider.getLocationPermissionManager() + .checkLocationPermission(activity!!) + result.success(checkResult.ordinal) + } + "requestLocationPermission" -> { + val callback = object : LocationPermissionCallback { + override fun onResult(locationPermission: LocationPermission) { + result.success(locationPermission.ordinal) + } + + override fun onError(errorCode: ErrorCodes) { + ErrorHandleUtils.handleMethodCallError(result, errorCode) + } + } + + serviceProvider.getLocationPermissionManager() + .requestLocationPermission(activity!!, callback) + } + "getLocation" -> { + val callback = object : LocationDataCallback { + override fun onUpdate(locationJson: String) { + // 매니저에서 stopLocationUpdates 처리 + result.success(locationJson) + } + + override fun onError(errorCode: ErrorCodes) { + // 매니저에서 stopLocationUpdates 처리 + ErrorHandleUtils.handleMethodCallError(result, errorCode) + } + } + + val argsMap = call.arguments as? Map<*, *> + val settings = LocationSettings.fromMap(argsMap) + + serviceProvider + .getLocationDataProviderManager() + .getLocation(callback, settings) + } + else -> result.notImplemented() + } + } + + override fun initChannel(messenger: BinaryMessenger) { + channel = MethodChannel(messenger, "plugins.pravera.com/fl_location") + channel.setMethodCallHandler(this) + } + + override fun setActivity(activity: Activity?) { + this.activity = activity + } + + override fun disposeChannel() { + if (::channel.isInitialized) { + channel.setMethodCallHandler(null) + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/errors/ErrorCodes.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/errors/ErrorCodes.kt new file mode 100644 index 000000000..722c3689a --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/errors/ErrorCodes.kt @@ -0,0 +1,24 @@ +package com.pravera.fl_location.errors + +enum class ErrorCodes { + ACTIVITY_NOT_ATTACHED, + LOCATION_PERMISSION_REQUEST_CANCELLED, + LOCATION_SETTINGS_CHANGE_FAILED, + LOCATION_SERVICES_NOT_AVAILABLE, + LOCATION_DATA_ENCODING_FAILED; + + fun message(): String { + return when (this) { + ACTIVITY_NOT_ATTACHED -> + "The function to use Activity is not available because Activity is not attached to FlutterEngine." + LOCATION_PERMISSION_REQUEST_CANCELLED -> + "The dialog was closed or the request was canceled during a runtime location permission request." + LOCATION_SETTINGS_CHANGE_FAILED -> + "The request to change location settings failed." + LOCATION_SERVICES_NOT_AVAILABLE -> + "Location services are not available." + LOCATION_DATA_ENCODING_FAILED -> + "Failed to encode location data in JSON format." + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationAccuracy.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationAccuracy.kt new file mode 100644 index 000000000..35cc4aec9 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationAccuracy.kt @@ -0,0 +1,36 @@ +package com.pravera.fl_location.models + +import com.google.android.gms.location.Priority + +enum class LocationAccuracy { + POWER_SAVE, + LOW, + BALANCED, + HIGH, + BEST, + NAVIGATION; + + companion object { + fun fromIndex(index: Int): LocationAccuracy { + return when (index) { + 1 -> LOW + 2 -> BALANCED + 3 -> HIGH + 4 -> BEST + 5 -> NAVIGATION + else -> POWER_SAVE + } + } + } + + fun toPriority(): Int { + return when (this) { + POWER_SAVE -> Priority.PRIORITY_LOW_POWER + LOW -> Priority.PRIORITY_LOW_POWER + BALANCED -> Priority.PRIORITY_BALANCED_POWER_ACCURACY + HIGH -> Priority.PRIORITY_HIGH_ACCURACY + BEST -> Priority.PRIORITY_HIGH_ACCURACY + NAVIGATION -> Priority.PRIORITY_HIGH_ACCURACY + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationData.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationData.kt new file mode 100644 index 000000000..8361fe1c3 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationData.kt @@ -0,0 +1,15 @@ +package com.pravera.fl_location.models + +import com.google.gson.annotations.SerializedName + +data class LocationData( + @SerializedName("latitude") val latitude: Double, + @SerializedName("longitude") val longitude: Double, + @SerializedName("accuracy") val accuracy: Double, + @SerializedName("altitude") val altitude: Double, + @SerializedName("heading") val heading: Double, + @SerializedName("speed") val speed: Double, + @SerializedName("speedAccuracy") val speedAccuracy: Double?, + @SerializedName("millisecondsSinceEpoch") val millisecondsSinceEpoch: Double, + @SerializedName("isMock") val isMock: Boolean? +) diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationPermission.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationPermission.kt new file mode 100644 index 000000000..de65e2d1f --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationPermission.kt @@ -0,0 +1,8 @@ +package com.pravera.fl_location.models + +enum class LocationPermission { + ALWAYS, + WHILE_IN_USE, + DENIED, + DENIED_FOREVER, +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationServicesStatus.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationServicesStatus.kt new file mode 100644 index 000000000..d96f0a314 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationServicesStatus.kt @@ -0,0 +1,6 @@ +package com.pravera.fl_location.models + +enum class LocationServicesStatus { + ENABLED, + DISABLED, +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationSettings.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationSettings.kt new file mode 100644 index 000000000..8f07c7fad --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/models/LocationSettings.kt @@ -0,0 +1,21 @@ +package com.pravera.fl_location.models + +data class LocationSettings( + val accuracy: LocationAccuracy, + val interval: Long? = null, + val distanceFilter: Float? = null +) { + companion object { + fun fromMap(map: Map<*, *>?): LocationSettings { + val accuracy = map?.get("accuracy").toString().toIntOrNull() ?: LocationAccuracy.BEST.ordinal + val interval = map?.get("interval").toString().toLongOrNull() + val distanceFilter = map?.get("distanceFilter").toString().toFloatOrNull() + + return LocationSettings( + accuracy = LocationAccuracy.fromIndex(accuracy), + interval = interval, + distanceFilter = distanceFilter + ) + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataCallback.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataCallback.kt new file mode 100644 index 000000000..9543ab594 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataCallback.kt @@ -0,0 +1,8 @@ +package com.pravera.fl_location.service + +import com.pravera.fl_location.errors.ErrorCodes + +interface LocationDataCallback { + fun onUpdate(locationJson: String) + fun onError(errorCode: ErrorCodes) +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataProvider.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataProvider.kt new file mode 100644 index 000000000..3e142c4c0 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataProvider.kt @@ -0,0 +1,177 @@ +package com.pravera.fl_location.service + +import android.app.Activity +import android.content.Context +import android.content.IntentSender +import android.os.Build +import android.os.Looper +import com.google.android.gms.common.api.ApiException +import com.google.android.gms.common.api.ResolvableApiException +import com.google.android.gms.location.* +import com.google.gson.Gson +import com.pravera.fl_location.errors.ErrorCodes +import com.pravera.fl_location.models.LocationData +import com.pravera.fl_location.models.LocationSettings + +class LocationDataProvider(private val context: Context) { + companion object { + private const val DEFAULT_LOCATION_INTERVAL = 5000L + private const val REQUEST_CHECK_SETTINGS = 0x1 + } + + private val jsonEncoder = Gson() + private val locationProvider = LocationServices.getFusedLocationProviderClient(context) + + private var activity: Activity? = null + private var callback: LocationDataCallback? = null + private var settings: LocationSettings? = null + + private var locationCallback: LocationCallback? = null + private var locationRequest: LocationRequest? = null + + var isRunningLocationUpdates = false + private set + + fun onActivityResult(requestCode: Int, resultCode: Int): Boolean { + if (requestCode == REQUEST_CHECK_SETTINGS) { + if (resultCode == Activity.RESULT_OK) { + // The stopLocationUpdates function has already been called. + if (callback == null) { + return false + } + startLocationUpdates() + return true + } else { + callback?.onError(ErrorCodes.LOCATION_SERVICES_NOT_AVAILABLE) + } + } + + return false + } + + fun setActivity(activity: Activity?) { + this.activity = activity + } + + fun requestLocationUpdates(callback: LocationDataCallback, settings: LocationSettings) { + stopLocationUpdates() + this.callback = callback + this.settings = settings + this.locationCallback = createLocationCallback(callback) + this.locationRequest = createLocationRequest(settings) + checkLocationSettingsAndStartLocationUpdates() + } + + private fun checkLocationSettingsAndStartLocationUpdates() { + val settingsRequest = LocationSettingsRequest.Builder() + .addLocationRequest(locationRequest!!) + .build() + + val settingsClient = LocationServices.getSettingsClient(context) + settingsClient.checkLocationSettings(settingsRequest) + .addOnSuccessListener { + startLocationUpdates() + } + .addOnFailureListener { + val statusCode: Int + if (it is ResolvableApiException) { + statusCode = it.statusCode + + // Location settings are not satisfied. + // But could be fixed by showing the user a dialog. + if (statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) { + try { + if (activity == null) { + callback?.onError(ErrorCodes.LOCATION_SETTINGS_CHANGE_FAILED) + return@addOnFailureListener + } + + it.startResolutionForResult(activity!!, REQUEST_CHECK_SETTINGS) + } catch (sendEx: IntentSender.SendIntentException) { + callback?.onError(ErrorCodes.LOCATION_SETTINGS_CHANGE_FAILED) + } + } else { + callback?.onError(ErrorCodes.LOCATION_SERVICES_NOT_AVAILABLE) + } + } else if (it is ApiException) { + statusCode = it.statusCode + + // Location settings are not satisfied. + // However, we have no way to fix the settings so we won't show the dialog. + if (statusCode == LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE) { + startLocationUpdates() + } else { + callback?.onError(ErrorCodes.LOCATION_SERVICES_NOT_AVAILABLE) + } + } else { + callback?.onError(ErrorCodes.LOCATION_SERVICES_NOT_AVAILABLE) + } + } + } + + private fun startLocationUpdates() { + if (locationRequest == null || locationCallback == null) return + + isRunningLocationUpdates = true + locationProvider.requestLocationUpdates( + locationRequest!!, locationCallback!!, Looper.getMainLooper()) + } + + fun stopLocationUpdates() { + if (locationCallback != null) { + isRunningLocationUpdates = false + locationProvider.removeLocationUpdates(locationCallback!!) + } + this.callback = null + this.settings = null + this.locationCallback = null + this.locationRequest = null + } + + private fun createLocationCallback(callback: LocationDataCallback): LocationCallback { + return object : LocationCallback() { + override fun onLocationResult(locationResult: LocationResult) { + val location = locationResult.lastLocation ?: return + + var speedAccuracy: Double? = null + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + speedAccuracy = location.speedAccuracyMetersPerSecond.toDouble() + } + + var isMock: Boolean? = null + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + isMock = location.isMock + } + + val locationData = LocationData( + latitude = location.latitude, + longitude = location.longitude, + accuracy = location.accuracy.toDouble(), + altitude = location.altitude, + heading = location.bearing.toDouble(), + speed = location.speed.toDouble(), + speedAccuracy = speedAccuracy, + millisecondsSinceEpoch = location.time.toDouble(), + isMock = isMock + ) + + try { + callback.onUpdate(jsonEncoder.toJson(locationData)) + } catch (ex: Exception) { + callback.onError(ErrorCodes.LOCATION_DATA_ENCODING_FAILED) + } + } + } + } + + private fun createLocationRequest(settings: LocationSettings): LocationRequest { + val accuracy = settings.accuracy.toPriority() + val interval = settings.interval ?: DEFAULT_LOCATION_INTERVAL + val distanceFilter = settings.distanceFilter ?: 0F + + return LocationRequest.Builder(accuracy, interval).apply { + setMinUpdateDistanceMeters(distanceFilter) + setMinUpdateIntervalMillis(interval) + }.build() + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataProviderManager.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataProviderManager.kt new file mode 100644 index 000000000..ccfe74f4e --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationDataProviderManager.kt @@ -0,0 +1,80 @@ +package com.pravera.fl_location.service + +import android.app.Activity +import android.content.Context +import android.content.Intent +import com.pravera.fl_location.errors.ErrorCodes +import com.pravera.fl_location.models.LocationSettings +import io.flutter.plugin.common.PluginRegistry + +class LocationDataProviderManager(private val context: Context): PluginRegistry.ActivityResultListener { + private val providers = mutableMapOf() + + private fun buildLocationDataProvider() = LocationDataProvider(context) + + fun setActivity(activity: Activity?) { + val iterator = providers.values.iterator() + for (provider in iterator) { + provider.setActivity(activity) + } + } + + fun getLocation(callback: LocationDataCallback, settings: LocationSettings): Int { + val newLocationDataProvider = buildLocationDataProvider() + val hashCode = newLocationDataProvider.hashCode() + providers[hashCode] = newLocationDataProvider + + val newCallback = object : LocationDataCallback { + override fun onUpdate(locationJson: String) { + if (newLocationDataProvider.isRunningLocationUpdates) { + stopLocationUpdates(hashCode) + callback.onUpdate(locationJson) + } + } + + override fun onError(errorCode: ErrorCodes) { + if (newLocationDataProvider.isRunningLocationUpdates) { + stopLocationUpdates(hashCode) + callback.onError(errorCode) + } + } + } + newLocationDataProvider.requestLocationUpdates(newCallback, settings) + return hashCode + } + + fun requestLocationUpdates(callback: LocationDataCallback, settings: LocationSettings): Int { + val newLocationDataProvider = buildLocationDataProvider() + val hashCode = newLocationDataProvider.hashCode() + providers[hashCode] = newLocationDataProvider + + newLocationDataProvider.requestLocationUpdates(callback, settings) + return hashCode + } + + fun stopLocationUpdates(hashCode: Int) { + providers[hashCode]?.let { + it.stopLocationUpdates() + providers.remove(hashCode) + } + } + + fun stopAllLocationUpdates() { + val iterator = providers.values.iterator() + for (provider in iterator) { + provider.stopLocationUpdates() + } + providers.clear() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { + val iterator = providers.values.iterator() + for (provider in iterator) { + if (provider.onActivityResult(requestCode, resultCode)) { + return true + } + } + + return false + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationPermissionCallback.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationPermissionCallback.kt new file mode 100644 index 000000000..dbc7068c5 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationPermissionCallback.kt @@ -0,0 +1,9 @@ +package com.pravera.fl_location.service + +import com.pravera.fl_location.errors.ErrorCodes +import com.pravera.fl_location.models.LocationPermission + +interface LocationPermissionCallback { + fun onResult(locationPermission: LocationPermission) + fun onError(errorCode: ErrorCodes) +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationPermissionManager.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationPermissionManager.kt new file mode 100644 index 000000000..2fdf7c1ad --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationPermissionManager.kt @@ -0,0 +1,169 @@ +package com.pravera.fl_location.service + +import android.Manifest +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import com.pravera.fl_location.errors.ErrorCodes +import com.pravera.fl_location.models.LocationPermission +import io.flutter.plugin.common.PluginRegistry + +class LocationPermissionManager: PluginRegistry.RequestPermissionsResultListener { + companion object { + private const val LOCATION_PERMISSION_REQ_CODE = 109 + private const val BACKGROUND_LOCATION_PERMISSION_REQ_CODE = 110 + private const val PREV_PERMISSION_STATUS_PREFS_NAME = "PREV_PERMISSION_STATUS_PREFS" + } + + private var activity: Activity? = null + private var callback: LocationPermissionCallback? = null + + fun checkLocationPermission(activity: Activity): LocationPermission { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) + return LocationPermission.ALWAYS + + val locationPermission = Manifest.permission.ACCESS_FINE_LOCATION + if (!activity.isPermissionGranted(locationPermission)) { + val prevPermissionStatus = activity.getPrevPermissionStatus(locationPermission) + if (prevPermissionStatus != null && + prevPermissionStatus == LocationPermission.DENIED_FOREVER && + !activity.shouldShowRequestPermissionRationale(locationPermission)) + return LocationPermission.DENIED_FOREVER + + return LocationPermission.DENIED + } + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) + return LocationPermission.ALWAYS + + val backgroundLocationPermission = Manifest.permission.ACCESS_BACKGROUND_LOCATION + if (activity.hasPermissionInManifest(backgroundLocationPermission) && + activity.isPermissionGranted(backgroundLocationPermission)) + return LocationPermission.ALWAYS + + return LocationPermission.WHILE_IN_USE + } + + fun requestLocationPermission(activity: Activity, callback: LocationPermissionCallback) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + callback.onResult(LocationPermission.ALWAYS) + return + } + + // The app has already requested location permission and is awaiting results. + if (this.callback != null) return + + this.activity = activity + this.callback = callback + + ActivityCompat.requestPermissions( + activity, + arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), + LOCATION_PERMISSION_REQ_CODE) + } + + private fun requestBackgroundLocationPermission(activity: Activity) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return + + ActivityCompat.requestPermissions( + activity, + arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), + BACKGROUND_LOCATION_PERMISSION_REQ_CODE) + } + + private fun Context.hasPermissionInManifest(permission: String): Boolean { + val packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS) + val permissions = packageInfo.requestedPermissions + + return permissions?.any { perm -> perm == permission } ?: false + } + + private fun Context.isPermissionGranted(permission: String): Boolean { + return ContextCompat.checkSelfPermission(this, permission) == + PackageManager.PERMISSION_GRANTED + } + + private fun Context.setPrevPermissionStatus(permission: String, status: LocationPermission) { + val prefs = getSharedPreferences( + PREV_PERMISSION_STATUS_PREFS_NAME, Context.MODE_PRIVATE) ?: return + + with (prefs.edit()) { + putString(permission, status.toString()) + commit() + } + } + + private fun Context.getPrevPermissionStatus(permission: String): LocationPermission? { + val prefs = getSharedPreferences( + PREV_PERMISSION_STATUS_PREFS_NAME, Context.MODE_PRIVATE) ?: return null + + val value = prefs.getString(permission, null) ?: return null + return LocationPermission.valueOf(value) + } + + private fun disposeResources() { + this.activity = null + this.callback = null + } + + @SuppressLint("InlinedApi") + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray): Boolean { + if (grantResults.isEmpty()) { + callback?.onError(ErrorCodes.LOCATION_PERMISSION_REQUEST_CANCELLED) + disposeResources() + return false + } + + val permission: String + val permissionIndex: Int + var permissionStatus = LocationPermission.DENIED + + when (requestCode) { + LOCATION_PERMISSION_REQ_CODE -> { + permission = Manifest.permission.ACCESS_FINE_LOCATION + permissionIndex = permissions.indexOf(permission) + + if (permissionIndex >= 0 && + grantResults[permissionIndex] == PackageManager.PERMISSION_GRANTED) { + permissionStatus = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) + LocationPermission.ALWAYS + else + LocationPermission.WHILE_IN_USE + } else { + if (activity?.shouldShowRequestPermissionRationale(permission) == false) + permissionStatus = LocationPermission.DENIED_FOREVER + } + } + BACKGROUND_LOCATION_PERMISSION_REQ_CODE -> { + permission = Manifest.permission.ACCESS_BACKGROUND_LOCATION + permissionIndex = permissions.indexOf(permission) + + permissionStatus = if (permissionIndex >= 0 && + grantResults[permissionIndex] == PackageManager.PERMISSION_GRANTED) + LocationPermission.ALWAYS + else + LocationPermission.WHILE_IN_USE + } + else -> return false + } + + activity?.setPrevPermissionStatus(permission, permissionStatus) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && + activity != null && + activity!!.hasPermissionInManifest(Manifest.permission.ACCESS_BACKGROUND_LOCATION) && + permission == Manifest.permission.ACCESS_FINE_LOCATION && + permissionStatus == LocationPermission.WHILE_IN_USE) { + requestBackgroundLocationPermission(activity!!) + } else { + callback?.onResult(permissionStatus) + disposeResources() + } + + return true + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusIntentService.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusIntentService.kt new file mode 100644 index 000000000..52d00e4ca --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusIntentService.kt @@ -0,0 +1,33 @@ +package com.pravera.fl_location.service + +import android.content.Context +import android.content.Intent +import androidx.core.app.JobIntentService +import com.pravera.fl_location.utils.LocationServicesUtils + +class LocationServicesStatusIntentService: JobIntentService() { + companion object { + private const val JOB_ID = 1000 + + fun enqueueWork(context: Context, intent: Intent) { + enqueueWork(context, LocationServicesStatusIntentService::class.java, JOB_ID, intent) + } + } + + override fun onHandleWork(intent: Intent) { + val currValue = LocationServicesUtils.checkLocationServicesStatus(applicationContext).toString() + + val prefs = getSharedPreferences( + LocationServicesStatusWatcher.LOCATION_SERVICES_STATUS_PREFS_NAME, + Context.MODE_PRIVATE) ?: return + + val prevValue = prefs.getString( + LocationServicesStatusWatcher.LOCATION_SERVICES_STATUS_PREFS_KEY, null) + if (currValue == prevValue) return + + with(prefs.edit()) { + putString(LocationServicesStatusWatcher.LOCATION_SERVICES_STATUS_PREFS_KEY, currValue) + commit() + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusReceiver.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusReceiver.kt new file mode 100644 index 000000000..c24708d3f --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusReceiver.kt @@ -0,0 +1,15 @@ +package com.pravera.fl_location.service + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.location.LocationManager + +class LocationServicesStatusReceiver: BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (intent.action != LocationManager.PROVIDERS_CHANGED_ACTION) return + + intent.setClass(context, LocationServicesStatusIntentService::class.java) + LocationServicesStatusIntentService.enqueueWork(context, intent) + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusWatcher.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusWatcher.kt new file mode 100644 index 000000000..ff460068a --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/LocationServicesStatusWatcher.kt @@ -0,0 +1,69 @@ +package com.pravera.fl_location.service + +import android.content.Context +import android.content.IntentFilter +import android.content.SharedPreferences +import android.location.LocationManager +import com.pravera.fl_location.models.LocationServicesStatus + +class LocationServicesStatusWatcher: SharedPreferences.OnSharedPreferenceChangeListener { + companion object { + const val LOCATION_SERVICES_STATUS_PREFS_NAME = "LOCATION_SERVICES_STATUS_PREFS" + const val LOCATION_SERVICES_STATUS_PREFS_KEY = "LOCATION_SERVICES_STATUS" + } + + private var onChangedCallback: ((LocationServicesStatus) -> Unit)? = null + private var broadcastReceiver: LocationServicesStatusReceiver? = null + + fun start(context: Context, onChanged: ((LocationServicesStatus) -> Unit)) { + if (this.onChangedCallback != null) stop(context) + + this.onChangedCallback = onChanged + context.registerSharedPreferenceChangeListener() + context.registerLocationServicesStatusIntentReceiver() + } + + fun stop(context: Context) { + this.onChangedCallback = null + context.unregisterSharedPreferenceChangeListener() + context.unregisterLocationServicesStatusIntentReceiver() + } + + private fun Context.registerSharedPreferenceChangeListener() { + val prefs = getSharedPreferences( + LOCATION_SERVICES_STATUS_PREFS_NAME, Context.MODE_PRIVATE) ?: return + + with (prefs.edit()) { + remove(LOCATION_SERVICES_STATUS_PREFS_KEY) + commit() + } + + prefs.registerOnSharedPreferenceChangeListener(this@LocationServicesStatusWatcher) + } + + private fun Context.unregisterSharedPreferenceChangeListener() { + val prefs = getSharedPreferences( + LOCATION_SERVICES_STATUS_PREFS_NAME, Context.MODE_PRIVATE) ?: return + prefs.unregisterOnSharedPreferenceChangeListener(this@LocationServicesStatusWatcher) + } + + private fun Context.registerLocationServicesStatusIntentReceiver() { + broadcastReceiver = LocationServicesStatusReceiver() + registerReceiver(broadcastReceiver, IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION)) + } + + private fun Context.unregisterLocationServicesStatusIntentReceiver() { + unregisterReceiver(broadcastReceiver) + broadcastReceiver = null + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { + when (key) { + LOCATION_SERVICES_STATUS_PREFS_KEY -> { + val value = sharedPreferences.getString(key, null) ?: return + val locationServicesStatus = LocationServicesStatus.valueOf(value) + onChangedCallback?.invoke(locationServicesStatus) + } + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/ServiceProvider.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/ServiceProvider.kt new file mode 100644 index 000000000..baf2973d3 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/service/ServiceProvider.kt @@ -0,0 +1,7 @@ +package com.pravera.fl_location.service + +interface ServiceProvider { + fun getLocationPermissionManager(): LocationPermissionManager + fun getLocationDataProviderManager(): LocationDataProviderManager + fun getLocationServicesStatusWatcher(): LocationServicesStatusWatcher +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/utils/ErrorHandleUtils.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/utils/ErrorHandleUtils.kt new file mode 100644 index 000000000..8f5f86ddc --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/utils/ErrorHandleUtils.kt @@ -0,0 +1,17 @@ +package com.pravera.fl_location.utils + +import com.pravera.fl_location.errors.ErrorCodes +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MethodChannel + +class ErrorHandleUtils { + companion object { + fun handleMethodCallError(result: MethodChannel.Result, errorCode: ErrorCodes) { + result.error(errorCode.toString(), errorCode.message(), null) + } + + fun handleStreamError(events: EventChannel.EventSink, errorCode: ErrorCodes) { + events.error(errorCode.toString(), errorCode.message(), null) + } + } +} diff --git a/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/utils/LocationServicesUtils.kt b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/utils/LocationServicesUtils.kt new file mode 100644 index 000000000..6d6be1dc4 --- /dev/null +++ b/third_party/pub_patches/fl_location/android/src/main/kotlin/com/pravera/fl_location/utils/LocationServicesUtils.kt @@ -0,0 +1,20 @@ +package com.pravera.fl_location.utils + +import android.content.Context +import android.location.LocationManager +import com.pravera.fl_location.models.LocationServicesStatus + +class LocationServicesUtils { + companion object { + fun checkLocationServicesStatus(context: Context): LocationServicesStatus { + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + val isGpsProviderEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) + val isNetProviderEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) + + return if (isGpsProviderEnabled || isNetProviderEnabled) + LocationServicesStatus.ENABLED + else + LocationServicesStatus.DISABLED + } + } +} diff --git a/third_party/pub_patches/fl_location/example/README.md b/third_party/pub_patches/fl_location/example/README.md new file mode 100644 index 000000000..8adc71c75 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/README.md @@ -0,0 +1,16 @@ +# fl_location_example + +Demonstrates how to use the fl_location plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/third_party/pub_patches/fl_location/example/android/app/build.gradle b/third_party/pub_patches/fl_location/example/android/app/build.gradle new file mode 100644 index 000000000..9d9c65c95 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/build.gradle @@ -0,0 +1,57 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 31 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + applicationId "com.pravera.fl_location_example" + minSdkVersion 21 + targetSdkVersion 31 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/third_party/pub_patches/fl_location/example/android/app/src/debug/AndroidManifest.xml b/third_party/pub_patches/fl_location/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..5a204f049 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/AndroidManifest.xml b/third_party/pub_patches/fl_location/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..a23ff6253 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/kotlin/com/pravera/fl_location_example/MainActivity.kt b/third_party/pub_patches/fl_location/example/android/app/src/main/kotlin/com/pravera/fl_location_example/MainActivity.kt new file mode 100644 index 000000000..5c17448cb --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/main/kotlin/com/pravera/fl_location_example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.pravera.fl_location_example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/drawable-v21/launch_background.xml b/third_party/pub_patches/fl_location/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/drawable/launch_background.xml b/third_party/pub_patches/fl_location/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..db77bb4b7 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..17987b79b Binary files /dev/null and b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09d439148 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5f1c8d34 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4d6372eeb Binary files /dev/null and b/third_party/pub_patches/fl_location/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/values-night/styles.xml b/third_party/pub_patches/fl_location/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..449a9f930 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/android/app/src/main/res/values/styles.xml b/third_party/pub_patches/fl_location/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..d74aa35c2 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/android/app/src/profile/AndroidManifest.xml b/third_party/pub_patches/fl_location/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..5a204f049 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/third_party/pub_patches/fl_location/example/android/build.gradle b/third_party/pub_patches/fl_location/example/android/build.gradle new file mode 100644 index 000000000..ba6fe4a43 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/third_party/pub_patches/fl_location/example/android/gradle.properties b/third_party/pub_patches/fl_location/example/android/gradle.properties new file mode 100644 index 000000000..94adc3a3f --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/third_party/pub_patches/fl_location/example/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/fl_location/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..cc5527d78 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/third_party/pub_patches/fl_location/example/android/settings.gradle b/third_party/pub_patches/fl_location/example/android/settings.gradle new file mode 100644 index 000000000..44e62bcf0 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/third_party/pub_patches/fl_location/example/ios/Flutter/AppFrameworkInfo.plist b/third_party/pub_patches/fl_location/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..9367d483e --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/third_party/pub_patches/fl_location/example/ios/Flutter/Debug.xcconfig b/third_party/pub_patches/fl_location/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..ec97fc6f3 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/fl_location/example/ios/Flutter/Release.xcconfig b/third_party/pub_patches/fl_location/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..c4855bfe2 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/fl_location/example/ios/Podfile b/third_party/pub_patches/fl_location/example/ios/Podfile new file mode 100644 index 000000000..1e8c3c90a --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/third_party/pub_patches/fl_location/example/ios/Podfile.lock b/third_party/pub_patches/fl_location/example/ios/Podfile.lock new file mode 100644 index 000000000..c15b65c87 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - fl_location (0.0.1): + - Flutter + - Flutter (1.0.0) + +DEPENDENCIES: + - fl_location (from `.symlinks/plugins/fl_location/ios`) + - Flutter (from `Flutter`) + +EXTERNAL SOURCES: + fl_location: + :path: ".symlinks/plugins/fl_location/ios" + Flutter: + :path: Flutter + +SPEC CHECKSUMS: + fl_location: 68b4a6c4aad2a453493ff66f196e0748280cf43e + Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.10.1 diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.pbxproj b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..d2f38e0f6 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3A2FF4D1939657022BD61D6F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09A1AA4F0F6FCAE48C75D407 /* Pods_Runner.framework */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 09A1AA4F0F6FCAE48C75D407 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 240244A9685D38C12E59345C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B8C213FA797AF9D6B1E063D6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + EF9A0BD320B79569C142D4ED /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A2FF4D1939657022BD61D6F /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F63284331C6C4585861AF52 /* Pods */ = { + isa = PBXGroup; + children = ( + B8C213FA797AF9D6B1E063D6 /* Pods-Runner.debug.xcconfig */, + EF9A0BD320B79569C142D4ED /* Pods-Runner.release.xcconfig */, + 240244A9685D38C12E59345C /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 1F63284331C6C4585861AF52 /* Pods */, + C838E5273D25FD5F48FFA498 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + C838E5273D25FD5F48FFA498 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 09A1AA4F0F6FCAE48C75D407 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + C8B6F6305BF18244B3C47F42 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 1F8149480FDA5DE173925972 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1F8149480FDA5DE173925972 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + C8B6F6305BF18244B3C47F42 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.pravera.flLocationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.pravera.flLocationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.pravera.flLocationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..a28140cfd --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/AppDelegate.swift b/third_party/pub_patches/fl_location/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..70693e4a8 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 000000000..dc9ada472 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 000000000..28c6bf030 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 000000000..f091b6b0b Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 000000000..4cde12118 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 000000000..d0ef06e7e Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 000000000..dcdc2306c Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 000000000..c8f9ed8f5 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 000000000..75b2d164a Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 000000000..c4df70d39 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 000000000..6a84f41e1 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 000000000..d0e1f5853 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000..0bedcf2fd --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/third_party/pub_patches/fl_location/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Base.lproj/Main.storyboard b/third_party/pub_patches/fl_location/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Info.plist b/third_party/pub_patches/fl_location/example/ios/Runner/Info.plist new file mode 100644 index 000000000..1a4abef93 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/Info.plist @@ -0,0 +1,56 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + fl_location_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + NSLocationWhenInUseUsageDescription + Used to collect location data. + NSLocationAlwaysAndWhenInUseUsageDescription + Used to collect location data in the background. + NSLocationAlwaysUsageDescription + Used to collect location data in the background. + UIBackgroundModes + + fetch + location + + + diff --git a/third_party/pub_patches/fl_location/example/ios/Runner/Runner-Bridging-Header.h b/third_party/pub_patches/fl_location/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..308a2a560 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/third_party/pub_patches/fl_location/example/lib/main.dart b/third_party/pub_patches/fl_location/example/lib/main.dart new file mode 100644 index 000000000..7aaf12956 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/lib/main.dart @@ -0,0 +1,181 @@ +import 'dart:async'; +// import 'dart:io'; + +import 'package:fl_location/fl_location.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +void main() => runApp(ExampleApp()); + +enum ButtonState { LOADING, DONE, DISABLED } + +class ExampleApp extends StatefulWidget { + @override + _ExampleAppState createState() => _ExampleAppState(); +} + +class _ExampleAppState extends State { + StreamSubscription? _locationSubscription; + + String _result = ''; + ButtonState _getLocationButtonState = ButtonState.DONE; + ButtonState _listenLocationStreamButtonState = ButtonState.DONE; + + Future _checkAndRequestPermission({bool? background}) async { + if (!await FlLocation.isLocationServicesEnabled) { + // Location services are disabled. + return false; + } + + var locationPermission = await FlLocation.checkLocationPermission(); + if (locationPermission == LocationPermission.deniedForever) { + // Cannot request runtime permission because location permission is denied forever. + return false; + } else if (locationPermission == LocationPermission.denied) { + // Ask the user for location permission. + locationPermission = await FlLocation.requestLocationPermission(); + if (locationPermission == LocationPermission.denied || + locationPermission == LocationPermission.deniedForever) return false; + } + + // Location permission must always be allowed (LocationPermission.always) + // to collect location data in the background. + if (background == true && + locationPermission == LocationPermission.whileInUse) return false; + + // Location services has been enabled and permission have been granted. + return true; + } + + void _refreshPage() { + setState(() {}); + } + + Future _getLocation() async { + if (await _checkAndRequestPermission()) { + _getLocationButtonState = ButtonState.LOADING; + _listenLocationStreamButtonState = ButtonState.DISABLED; + _refreshPage(); + + final timeLimit = const Duration(seconds: 10); + await FlLocation.getLocation(timeLimit: timeLimit).then((location) { + _result = location.toJson().toString(); + }).onError((error, stackTrace) { + _result = error.toString(); + }).whenComplete(() { + _getLocationButtonState = ButtonState.DONE; + _listenLocationStreamButtonState = ButtonState.DONE; + _refreshPage(); + }); + } + } + + Future _listenLocationStream() async { + if (await _checkAndRequestPermission()) { + if (_locationSubscription != null) await _cancelLocationSubscription(); + + _locationSubscription = FlLocation.getLocationStream() + .handleError(_handleError) + .listen((event) { + _result = event.toJson().toString(); + _refreshPage(); + }); + + _getLocationButtonState = ButtonState.DISABLED; + _refreshPage(); + } + } + + Future _cancelLocationSubscription() async { + await _locationSubscription?.cancel(); + _locationSubscription = null; + + _getLocationButtonState = ButtonState.DONE; + _refreshPage(); + } + + void _handleError(dynamic error, StackTrace stackTrace) { + _result = error.toString(); + _refreshPage(); + } + + @override + void initState() { + super.initState(); + // The getLocationServicesStatusStream function is not available in Web. + if (!kIsWeb) { + FlLocation.getLocationServicesStatusStream().listen((event) { + print('location services status: $event'); + }); + } + } + + @override + void dispose() { + _locationSubscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: _buildContentView(), + ), + ); + } + + Widget _buildContentView() { + final buttonList = Column( + children: [ + const SizedBox(height: 8.0), + _buildTestButton( + text: 'GET Location', + state: _getLocationButtonState, + onPressed: _getLocation, + ), + const SizedBox(height: 8.0), + _buildTestButton( + text: _locationSubscription == null + ? 'Listen LocationStream' + : 'Cancel LocationSubscription', + state: _listenLocationStreamButtonState, + onPressed: _locationSubscription == null + ? _listenLocationStream + : _cancelLocationSubscription, + ), + ], + ); + + final resultText = + Text(_result, style: Theme.of(context).textTheme.bodyText1); + + return ListView( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + children: [ + buttonList, + const SizedBox(height: 10.0), + resultText, + ], + ); + } + + Widget _buildTestButton({ + required String text, + required ButtonState state, + required VoidCallback? onPressed, + }) { + return ElevatedButton( + child: state == ButtonState.LOADING + ? SizedBox.fromSize( + size: const Size(20.0, 20.0), + child: const CircularProgressIndicator(strokeWidth: 2.0), + ) + : Text(text), + onPressed: state == ButtonState.DONE ? onPressed : null, + ); + } +} diff --git a/third_party/pub_patches/fl_location/example/pubspec.yaml b/third_party/pub_patches/fl_location/example/pubspec.yaml new file mode 100644 index 000000000..e2c162b77 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/pubspec.yaml @@ -0,0 +1,26 @@ +name: fl_location_example +description: Demonstrates how to use the fl_location plugin. +publish_to: 'none' + +environment: + sdk: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" + +dependencies: + flutter: + sdk: flutter + + fl_location: + # When depending on this package from a real application you should use: + # fl_location: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/third_party/pub_patches/fl_location/example/test/widget_test.dart b/third_party/pub_patches/fl_location/example/test/widget_test.dart new file mode 100644 index 000000000..153f05566 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/test/widget_test.dart @@ -0,0 +1,3 @@ +void main() { + +} diff --git a/third_party/pub_patches/fl_location/example/web/favicon.png b/third_party/pub_patches/fl_location/example/web/favicon.png new file mode 100644 index 000000000..8aaa46ac1 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/web/favicon.png differ diff --git a/third_party/pub_patches/fl_location/example/web/icons/Icon-192.png b/third_party/pub_patches/fl_location/example/web/icons/Icon-192.png new file mode 100644 index 000000000..b749bfef0 Binary files /dev/null and b/third_party/pub_patches/fl_location/example/web/icons/Icon-192.png differ diff --git a/third_party/pub_patches/fl_location/example/web/icons/Icon-512.png b/third_party/pub_patches/fl_location/example/web/icons/Icon-512.png new file mode 100644 index 000000000..88cfd48df Binary files /dev/null and b/third_party/pub_patches/fl_location/example/web/icons/Icon-512.png differ diff --git a/third_party/pub_patches/fl_location/example/web/index.html b/third_party/pub_patches/fl_location/example/web/index.html new file mode 100644 index 000000000..e9869bbec --- /dev/null +++ b/third_party/pub_patches/fl_location/example/web/index.html @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + fl_location_example + + + + + + + diff --git a/third_party/pub_patches/fl_location/example/web/manifest.json b/third_party/pub_patches/fl_location/example/web/manifest.json new file mode 100644 index 000000000..166f121e9 --- /dev/null +++ b/third_party/pub_patches/fl_location/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "fl_location_example", + "short_name": "fl_location_example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "Demonstrates how to use the fl_location plugin.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/FlLocationPlugin.h b/third_party/pub_patches/fl_location/ios/Classes/FlLocationPlugin.h new file mode 100644 index 000000000..78cec9b43 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/FlLocationPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FlLocationPlugin : NSObject +@end diff --git a/third_party/pub_patches/fl_location/ios/Classes/FlLocationPlugin.m b/third_party/pub_patches/fl_location/ios/Classes/FlLocationPlugin.m new file mode 100644 index 000000000..e750ad8f4 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/FlLocationPlugin.m @@ -0,0 +1,15 @@ +#import "FlLocationPlugin.h" +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "fl_location-Swift.h" +#endif + +@implementation FlLocationPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftFlLocationPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/third_party/pub_patches/fl_location/ios/Classes/LocationServicesStatusStreamHandlerImpl.swift b/third_party/pub_patches/fl_location/ios/Classes/LocationServicesStatusStreamHandlerImpl.swift new file mode 100644 index 000000000..3b56d4efd --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/LocationServicesStatusStreamHandlerImpl.swift @@ -0,0 +1,33 @@ +// +// LocationServicesStatusStreamHandlerImpl.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/27. +// + +import Flutter +import Foundation + +class LocationServicesStatusStreamHandlerImpl: NSObject, FlutterStreamHandler { + private let channel: FlutterEventChannel + private let serviceProvider: ServiceProvider + + init(messenger: FlutterBinaryMessenger, serviceProvider: ServiceProvider) { + self.serviceProvider = serviceProvider + self.channel = FlutterEventChannel(name: "plugins.pravera.com/fl_location/location_services_status", binaryMessenger: messenger) + super.init() + self.channel.setStreamHandler(self) + } + + func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { + serviceProvider.getLocationServicesStatusWatcher().start { (locationServicesStatus) in + events(locationServicesStatus.rawValue) + } + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + serviceProvider.getLocationServicesStatusWatcher().stop() + return nil + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/LocationStreamHandlerImpl.swift b/third_party/pub_patches/fl_location/ios/Classes/LocationStreamHandlerImpl.swift new file mode 100644 index 000000000..3dd7dbf0c --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/LocationStreamHandlerImpl.swift @@ -0,0 +1,55 @@ +// +// LocationStreamHandlerImpl.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/29. +// + +import Flutter +import Foundation + +class LocationStreamHandlerImpl: NSObject, FlutterStreamHandler, LocationDataHandler { + private let channel: FlutterEventChannel + private let serviceProvider: ServiceProvider + + private var locationEventSink: FlutterEventSink? = nil + private var locationDataProviderHashCode: Int? = nil + + init(messenger: FlutterBinaryMessenger, serviceProvider: ServiceProvider) { + self.serviceProvider = serviceProvider + self.channel = FlutterEventChannel(name: "plugins.pravera.com/fl_location/updates", binaryMessenger: messenger) + super.init() + self.channel.setStreamHandler(self) + } + + func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { + let argsDict = arguments as? Dictionary + let settings = LocationSettings(from: argsDict) + + locationEventSink = events + locationDataProviderHashCode = serviceProvider + .getLocationDataProviderManager() + .startUpdatingLocation(handler: self, settings: settings) + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + locationEventSink = nil + if locationDataProviderHashCode != nil { + serviceProvider + .getLocationDataProviderManager() + .stopUpdatingLocation(hashCode: locationDataProviderHashCode!) + locationDataProviderHashCode = nil + } + return nil + } + + func onLocationUpdate(locationJson: String) { + locationEventSink?(locationJson) + } + + func onLocationError(errorCode: ErrorCodes) { + if locationEventSink == nil { return } + ErrorHandleUtils.handleStreamError(events: locationEventSink!, errorCode: errorCode) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/MethodCallHandlerImpl.swift b/third_party/pub_patches/fl_location/ios/Classes/MethodCallHandlerImpl.swift new file mode 100644 index 000000000..7f35b5272 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/MethodCallHandlerImpl.swift @@ -0,0 +1,44 @@ +// +// MethodCallHandlerImpl.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/26. +// + +import Flutter +import Foundation + +class MethodCallHandlerImpl: NSObject { + private let channel: FlutterMethodChannel + private let serviceProvider: ServiceProvider + + init(messenger: FlutterBinaryMessenger, serviceProvider: ServiceProvider) { + self.channel = FlutterMethodChannel(name: "plugins.pravera.com/fl_location", binaryMessenger: messenger) + self.serviceProvider = serviceProvider + super.init() + self.channel.setMethodCallHandler(onMethodCall) + } + + func onMethodCall(call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "checkLocationServicesStatus": + result(LocationServicesUtils.checkLocationServicesStatus().rawValue) + case "checkLocationPermission": + let handler = LocationPermissionHandlerImpl(result) + serviceProvider.getLocationPermissionManager().checkLocationPermission(handler: handler) + case "requestLocationPermission": + let handler = LocationPermissionHandlerImpl(result) + serviceProvider.getLocationPermissionManager().requestLocationPermission(handler: handler) + case "getLocation": + let argsDict = call.arguments as? Dictionary + let settings = LocationSettings(from: argsDict) + + let handler = LocationDataHandlerImpl(result) + serviceProvider + .getLocationDataProviderManager() + .getLocation(handler: handler, settings: settings) + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/SwiftFlLocationPlugin.swift b/third_party/pub_patches/fl_location/ios/Classes/SwiftFlLocationPlugin.swift new file mode 100644 index 000000000..0f1f14006 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/SwiftFlLocationPlugin.swift @@ -0,0 +1,36 @@ +import Flutter +import UIKit + +public class SwiftFlLocationPlugin: NSObject, FlutterPlugin, ServiceProvider { + private var locationPermissionManager: LocationPermissionManager? = nil + private var locationDataProviderManager: LocationDataProviderManager? = nil + private var locationServicesStatusWatcher: LocationServicesStatusWatcher? = nil + + private var methodCallHandler: MethodCallHandlerImpl? = nil + private var locationStreamHandler: LocationStreamHandlerImpl? = nil + private var locationServicesStatusStreamHandler: LocationServicesStatusStreamHandlerImpl? = nil + + public static func register(with registrar: FlutterPluginRegistrar) { + let instance = SwiftFlLocationPlugin() + instance.initServices() + instance.initChannels(registrar.messenger()) + } + + private func initServices() { + locationPermissionManager = LocationPermissionManager() + locationDataProviderManager = LocationDataProviderManager() + locationServicesStatusWatcher = LocationServicesStatusWatcher() + } + + private func initChannels(_ messenger: FlutterBinaryMessenger) { + methodCallHandler = MethodCallHandlerImpl(messenger: messenger, serviceProvider: self) + locationStreamHandler = LocationStreamHandlerImpl(messenger: messenger, serviceProvider: self) + locationServicesStatusStreamHandler = LocationServicesStatusStreamHandlerImpl(messenger: messenger, serviceProvider: self) + } + + func getLocationPermissionManager() -> LocationPermissionManager { return locationPermissionManager! } + + func getLocationDataProviderManager() -> LocationDataProviderManager { return locationDataProviderManager! } + + func getLocationServicesStatusWatcher() -> LocationServicesStatusWatcher { return locationServicesStatusWatcher! } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/errors/ErrorCodes.swift b/third_party/pub_patches/fl_location/ios/Classes/errors/ErrorCodes.swift new file mode 100644 index 000000000..2e681c3fe --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/errors/ErrorCodes.swift @@ -0,0 +1,25 @@ +// +// ErrorCodes.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/27. +// + +import Foundation + +enum ErrorCodes: String { + case LOCATION_USAGE_DESCRIPTION_NOT_FOUND + case LOCATION_UPDATE_FAILED + case LOCATION_DATA_ENCODING_FAILED + + func message() -> String { + switch self { + case .LOCATION_USAGE_DESCRIPTION_NOT_FOUND: + return "The location usage description key could not be found in the Info.plist file. You are required to include the NSLocationWhenInUseUsageDescription and NSLocationAlwaysAndWhenInUsageDescription keys in your app's Info.plist file. (If your app supports iOS 10 and earlier, the NSLocationAlwaysUsageDescription key is also required.) If those keys are not present, authorization requests fail immediately." + case .LOCATION_UPDATE_FAILED: + return "Location data could not be obtained because location update failed." + case .LOCATION_DATA_ENCODING_FAILED: + return "Failed to encode location data in JSON format." + } + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/models/LocationAccuracy.swift b/third_party/pub_patches/fl_location/ios/Classes/models/LocationAccuracy.swift new file mode 100644 index 000000000..56eb8fd53 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/models/LocationAccuracy.swift @@ -0,0 +1,52 @@ +// +// LocationAccuracy.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/28. +// + +import CoreLocation +import Foundation + +enum LocationAccuracy: Int { + case POWER_SAVE = 0 + case LOW = 1 + case BALANCED = 2 + case HIGH = 3 + case BEST = 4 + case NAVIGATION = 5 + + static func fromIndex(index: Int) -> LocationAccuracy { + switch index { + case 1: + return .LOW + case 2: + return .BALANCED + case 3: + return .HIGH + case 4: + return .BEST + case 5: + return .NAVIGATION + default: + return .POWER_SAVE + } + } + + func toCLLocationAccuracy() -> CLLocationAccuracy { + switch self { + case .POWER_SAVE: + return kCLLocationAccuracyThreeKilometers + case .LOW: + return kCLLocationAccuracyKilometer + case .BALANCED: + return kCLLocationAccuracyHundredMeters + case .HIGH: + return kCLLocationAccuracyNearestTenMeters + case .BEST: + return kCLLocationAccuracyBest + case .NAVIGATION: + return kCLLocationAccuracyBestForNavigation + } + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/models/LocationData.swift b/third_party/pub_patches/fl_location/ios/Classes/models/LocationData.swift new file mode 100644 index 000000000..69ecc8b83 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/models/LocationData.swift @@ -0,0 +1,39 @@ +// +// LocationData.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/29. +// + +import CoreLocation +import Foundation + +struct LocationData: Codable { + let latitude: Double + let longitude: Double + let accuracy: Double + let altitude: Double + let heading: Double + let speed: Double + let speedAccuracy: Double + let millisecondsSinceEpoch: Double + let isMock: Bool + + init(from location: CLLocation) { + self.latitude = location.coordinate.latitude + self.longitude = location.coordinate.longitude + self.accuracy = location.horizontalAccuracy + self.altitude = location.altitude + self.heading = location.course + self.speed = location.speed + + if #available(iOS 10.0, *) { + self.speedAccuracy = location.speedAccuracy + } else { + self.speedAccuracy = 0.0 + } + + self.millisecondsSinceEpoch = location.timestamp.timeIntervalSince1970 * 1000.0 + self.isMock = false + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/models/LocationPermission.swift b/third_party/pub_patches/fl_location/ios/Classes/models/LocationPermission.swift new file mode 100644 index 000000000..8482824d0 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/models/LocationPermission.swift @@ -0,0 +1,31 @@ +// +// LocationPermission.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/26. +// + +import CoreLocation +import Foundation + +enum LocationPermission: Int { + case ALWAYS = 0 + case WHILE_IN_USE = 1 + case DENIED = 2 + case DENIED_FOREVER = 3 + + static func fromAuthorizationStatus(status: CLAuthorizationStatus) -> LocationPermission { + switch status { + case .authorizedAlways: + return LocationPermission.ALWAYS + case .authorizedWhenInUse: + return LocationPermission.WHILE_IN_USE + case .notDetermined, .restricted: + return LocationPermission.DENIED + case .denied: + return LocationPermission.DENIED_FOREVER + default: + return LocationPermission.DENIED + } + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/models/LocationServicesStatus.swift b/third_party/pub_patches/fl_location/ios/Classes/models/LocationServicesStatus.swift new file mode 100644 index 000000000..4bb2f305a --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/models/LocationServicesStatus.swift @@ -0,0 +1,13 @@ +// +// LocationServicesStatus.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/26. +// + +import Foundation + +enum LocationServicesStatus: Int { + case ENABLED = 0 + case DISABLED = 1 +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/models/LocationSettings.swift b/third_party/pub_patches/fl_location/ios/Classes/models/LocationSettings.swift new file mode 100644 index 000000000..c817f9f41 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/models/LocationSettings.swift @@ -0,0 +1,24 @@ +// +// LocationSettings.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/29. +// + +import Foundation + +class LocationSettings { + let accuracy: LocationAccuracy + let interval: Int? + let distanceFilter: Double? + + init(from dictionary: Dictionary?) { + let rAccuracy = dictionary?["accuracy"] as? Int ?? LocationAccuracy.BEST.rawValue + let rInterval = dictionary?["interval"] as? Int + let rDistanceFilter = dictionary?["distanceFilter"] as? Double + + self.accuracy = LocationAccuracy.fromIndex(index: rAccuracy) + self.interval = rInterval + self.distanceFilter = rDistanceFilter + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandler.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandler.swift new file mode 100644 index 000000000..fa71b3d92 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandler.swift @@ -0,0 +1,13 @@ +// +// LocationDataHandler.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/29. +// + +import Foundation + +protocol LocationDataHandler { + func onLocationUpdate(locationJson: String) + func onLocationError(errorCode: ErrorCodes) +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandlerImpl.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandlerImpl.swift new file mode 100644 index 000000000..9504d8575 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandlerImpl.swift @@ -0,0 +1,24 @@ +// +// LocationDataHandlerImpl.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/08/09. +// + +import Foundation + +class LocationDataHandlerImpl: NSObject, LocationDataHandler { + private let result: FlutterResult + + init(_ result: @escaping FlutterResult) { + self.result = result + } + + func onLocationUpdate(locationJson: String) { + result(locationJson) + } + + func onLocationError(errorCode: ErrorCodes) { + ErrorHandleUtils.handleMethodCallError(result: result, errorCode: errorCode) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandlerImplForManager.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandlerImplForManager.swift new file mode 100644 index 000000000..4b83cb040 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataHandlerImplForManager.swift @@ -0,0 +1,28 @@ +// +// LocationDataHandlerImplForManager.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/08/09. +// + +import Foundation + +class LocationDataHandlerImplForManager: NSObject, LocationDataHandler { + private let handler: LocationDataHandler + private let onComplete: () -> Void + + init(_ handler: LocationDataHandler, onComplete: @escaping () -> Void) { + self.handler = handler + self.onComplete = onComplete + } + + func onLocationUpdate(locationJson: String) { + onComplete() + handler.onLocationUpdate(locationJson: locationJson) + } + + func onLocationError(errorCode: ErrorCodes) { + onComplete() + handler.onLocationError(errorCode: errorCode) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataProvider.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataProvider.swift new file mode 100644 index 000000000..375e99e1d --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataProvider.swift @@ -0,0 +1,68 @@ +// +// LocationDataProvider.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/28. +// + +import CoreLocation +import Foundation + +class LocationDataProvider: NSObject, CLLocationManagerDelegate { + private let jsonEncoder: JSONEncoder + private let locationManager: CLLocationManager + + private var handler: LocationDataHandler? = nil + private var settings: LocationSettings? = nil + + override init() { + self.jsonEncoder = JSONEncoder() + self.locationManager = CLLocationManager() + super.init() + self.locationManager.delegate = self + } + + func startUpdatingLocation(handler: LocationDataHandler, settings: LocationSettings) { + if self.handler != nil { stopUpdatingLocation() } + + self.handler = handler + self.settings = settings + + self.locationManager.desiredAccuracy = settings.accuracy.toCLLocationAccuracy() + self.locationManager.distanceFilter = settings.distanceFilter ?? kCLDistanceFilterNone + self.locationManager.allowsBackgroundLocationUpdates = containsBackgroundLocationMode() + + self.locationManager.startUpdatingLocation() + } + + func stopUpdatingLocation() { + self.locationManager.stopUpdatingLocation() + + self.handler = nil + self.settings = nil + } + + func containsBackgroundLocationMode() -> Bool { + let backgroundModes = Bundle.main.object(forInfoDictionaryKey: "UIBackgroundModes") as? NSArray + return backgroundModes?.contains("location") ?? false + } + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + if handler == nil { return } + + do { + let locationData = LocationData(from: locations.last!) + guard let locationJson = String(data: try jsonEncoder.encode(locationData), encoding: .utf8) else { return } + handler?.onLocationUpdate(locationJson: locationJson) + } catch { + handler?.onLocationError(errorCode: ErrorCodes.LOCATION_DATA_ENCODING_FAILED) + } + } + + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + if handler == nil { return } + + NSLog("LOCATION_UPDATE_FAILED: \(error)") + handler?.onLocationError(errorCode: ErrorCodes.LOCATION_UPDATE_FAILED) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataProviderManager.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataProviderManager.swift new file mode 100644 index 000000000..42d20c098 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationDataProviderManager.swift @@ -0,0 +1,45 @@ +// +// LocationDataProviderManager.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/08/06. +// + +import Foundation + +class LocationDataProviderManager: NSObject { + private var providers = Dictionary() + + private func buildLocationDataProvider() -> LocationDataProvider { + return LocationDataProvider() + } + + func getLocation(handler: LocationDataHandler, settings: LocationSettings) -> Int { + let newLocationDataProvider = buildLocationDataProvider() + let hashCode = newLocationDataProvider.hash + providers[hashCode] = newLocationDataProvider + + let newHandler = LocationDataHandlerImplForManager(handler) { + self.stopUpdatingLocation(hashCode: hashCode) + } + + newLocationDataProvider.startUpdatingLocation(handler: newHandler, settings: settings) + return hashCode + } + + func startUpdatingLocation(handler: LocationDataHandler, settings: LocationSettings) -> Int { + let newLocationDataProvider = buildLocationDataProvider() + let hashCode = newLocationDataProvider.hash + providers[hashCode] = newLocationDataProvider + + newLocationDataProvider.startUpdatingLocation(handler: handler, settings: settings) + return hashCode + } + + func stopUpdatingLocation(hashCode: Int) { + guard let locationDataProvider = providers[hashCode] else { return } + + locationDataProvider.stopUpdatingLocation() + providers.removeValue(forKey: hashCode) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionHandler.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionHandler.swift new file mode 100644 index 000000000..5d730b8b3 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionHandler.swift @@ -0,0 +1,13 @@ +// +// LocationPermissionHandler.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/29. +// + +import Foundation + +protocol LocationPermissionHandler { + func onPermissionResult(locationPermission: LocationPermission) + func onPermissionError(errorCode: ErrorCodes) +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionHandlerImpl.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionHandlerImpl.swift new file mode 100644 index 000000000..4357b7e74 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionHandlerImpl.swift @@ -0,0 +1,24 @@ +// +// LocationPermissionHandlerImpl.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/08/09. +// + +import Foundation + +class LocationPermissionHandlerImpl: NSObject, LocationPermissionHandler { + private let result: FlutterResult + + init(_ result: @escaping FlutterResult) { + self.result = result + } + + func onPermissionResult(locationPermission: LocationPermission) { + result(locationPermission.rawValue) + } + + func onPermissionError(errorCode: ErrorCodes) { + ErrorHandleUtils.handleMethodCallError(result: result, errorCode: errorCode) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionManager.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionManager.swift new file mode 100644 index 000000000..429d19eb2 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationPermissionManager.swift @@ -0,0 +1,75 @@ +// +// LocationPermissionManager.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/26. +// + +import CoreLocation +import Foundation + +class LocationPermissionManager: NSObject, CLLocationManagerDelegate { + private let locationManager: CLLocationManager + + private var handler: LocationPermissionHandler? = nil + + override init() { + self.locationManager = CLLocationManager() + super.init() + self.locationManager.delegate = self + } + + func checkLocationPermission(handler: LocationPermissionHandler) { + let status = CLLocationManager.authorizationStatus() + let result = LocationPermission.fromAuthorizationStatus(status: status) + handler.onPermissionResult(locationPermission: result) + } + + func requestLocationPermission(handler: LocationPermissionHandler) { + // The app has already requested location permission and is awaiting results. + if self.handler != nil { return } + + self.handler = handler + + if containsLocationAlwaysUsageDescription() { + locationManager.requestAlwaysAuthorization() + } else if containsLocationWhenInUseUsageDescription() { + locationManager.requestWhenInUseAuthorization() + } else { + handler.onPermissionError(errorCode: ErrorCodes.LOCATION_USAGE_DESCRIPTION_NOT_FOUND) + disposeResources() + } + } + + func containsLocationAlwaysUsageDescription() -> Bool { + if #available(iOS 11.0, *) { + return Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysAndWhenInUseUsageDescription") != nil + } else { + return Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil + } + } + + func containsLocationWhenInUseUsageDescription() -> Bool { + return Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil + } + + private func disposeResources() { + self.handler = nil + } + + @available(iOS, introduced: 4.2, deprecated: 14.0) + func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { + if handler == nil { return } + + checkLocationPermission(handler: handler!) + disposeResources() + } + + @available(iOS 14.0, *) + func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { + if handler == nil { return } + + checkLocationPermission(handler: handler!) + disposeResources() + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/LocationServicesStatusWatcher.swift b/third_party/pub_patches/fl_location/ios/Classes/service/LocationServicesStatusWatcher.swift new file mode 100644 index 000000000..0c88e69df --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/LocationServicesStatusWatcher.swift @@ -0,0 +1,58 @@ +// +// LocationServicesStatusWatcher.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/27. +// + +import CoreLocation +import Foundation + +typealias LocationServicesStatusChangeHandler = (LocationServicesStatus) -> Void + +class LocationServicesStatusWatcher: NSObject, CLLocationManagerDelegate { + private let locationManager: CLLocationManager + + private var handler: LocationServicesStatusChangeHandler? = nil + private var prevLocationServicesStatus: LocationServicesStatus? = nil + + override init() { + self.locationManager = CLLocationManager() + super.init() + self.locationManager.delegate = self + } + + func start(handler: @escaping LocationServicesStatusChangeHandler) { + if self.handler != nil { stop() } + + self.handler = handler + self.prevLocationServicesStatus = LocationServicesUtils.checkLocationServicesStatus() + } + + func stop() { + self.handler = nil + self.prevLocationServicesStatus = nil + } + + func checkLocationServicesStatusChange(handler: LocationServicesStatusChangeHandler) { + let currLocationServicesStatus = LocationServicesUtils.checkLocationServicesStatus() + if currLocationServicesStatus == prevLocationServicesStatus { return } + + handler(currLocationServicesStatus) + prevLocationServicesStatus = currLocationServicesStatus + } + + @available(iOS, introduced: 4.2, deprecated: 14.0) + func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { + if handler == nil { return } + + checkLocationServicesStatusChange(handler: handler!) + } + + @available(iOS 14.0, *) + func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { + if handler == nil { return } + + checkLocationServicesStatusChange(handler: handler!) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/service/ServiceProvider.swift b/third_party/pub_patches/fl_location/ios/Classes/service/ServiceProvider.swift new file mode 100644 index 000000000..3bd7cae5b --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/service/ServiceProvider.swift @@ -0,0 +1,14 @@ +// +// ServiceProvider.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/27. +// + +import Foundation + +protocol ServiceProvider { + func getLocationPermissionManager() -> LocationPermissionManager + func getLocationDataProviderManager() -> LocationDataProviderManager + func getLocationServicesStatusWatcher() -> LocationServicesStatusWatcher +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/utils/ErrorHandleUtils.swift b/third_party/pub_patches/fl_location/ios/Classes/utils/ErrorHandleUtils.swift new file mode 100644 index 000000000..d59f891e8 --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/utils/ErrorHandleUtils.swift @@ -0,0 +1,21 @@ +// +// ErrorHandleUtils.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/27. +// + +import Flutter +import Foundation + +class ErrorHandleUtils { + static func handleMethodCallError(result: FlutterResult, errorCode: ErrorCodes) { + let error = FlutterError(code: errorCode.rawValue, message: errorCode.message(), details: nil) + result(error) + } + + static func handleStreamError(events: FlutterEventSink, errorCode: ErrorCodes) { + let error = FlutterError(code: errorCode.rawValue, message: errorCode.message(), details: nil) + events(error) + } +} diff --git a/third_party/pub_patches/fl_location/ios/Classes/utils/LocationServicesUtils.swift b/third_party/pub_patches/fl_location/ios/Classes/utils/LocationServicesUtils.swift new file mode 100644 index 000000000..e3f05712e --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/Classes/utils/LocationServicesUtils.swift @@ -0,0 +1,19 @@ +// +// LocationServicesUtils.swift +// fl_location +// +// Created by WOO JIN HWANG on 2021/07/26. +// + +import CoreLocation +import Foundation + +class LocationServicesUtils { + static func checkLocationServicesStatus() -> LocationServicesStatus { + if CLLocationManager.locationServicesEnabled() { + return LocationServicesStatus.ENABLED + } else { + return LocationServicesStatus.DISABLED + } + } +} diff --git a/third_party/pub_patches/fl_location/ios/fl_location.podspec b/third_party/pub_patches/fl_location/ios/fl_location.podspec new file mode 100644 index 000000000..b898e0f7d --- /dev/null +++ b/third_party/pub_patches/fl_location/ios/fl_location.podspec @@ -0,0 +1,23 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint fl_location.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'fl_location' + s.version = '0.0.1' + s.summary = 'A new Flutter project.' + s.description = <<-DESC +A new Flutter project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '8.0' + + # Flutter.framework does not contain a i386 slice. + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } + s.swift_version = '5.0' +end diff --git a/third_party/pub_patches/fl_location/lib/fl_location.dart b/third_party/pub_patches/fl_location/lib/fl_location.dart new file mode 100644 index 000000000..642e7d991 --- /dev/null +++ b/third_party/pub_patches/fl_location/lib/fl_location.dart @@ -0,0 +1,39 @@ +import 'package:fl_location_platform_interface/fl_location_platform_interface.dart'; +export 'package:fl_location_platform_interface/fl_location_platform_interface.dart'; + +class FlLocation { + /// Whether location services are enabled. + static Future get isLocationServicesEnabled => + FlLocationPlatform.instance.isLocationServicesEnabled(); + + /// Check location permission. + static Future checkLocationPermission() => + FlLocationPlatform.instance.checkLocationPermission(); + + /// Request location permission. + static Future requestLocationPermission() => + FlLocationPlatform.instance.requestLocationPermission(); + + /// Get the current location. + static Future getLocation({ + LocationAccuracy accuracy = LocationAccuracy.best, + Duration? timeLimit, + }) => + FlLocationPlatform.instance + .getLocation(accuracy: accuracy, timeLimit: timeLimit); + + /// Get the location stream. + static Stream getLocationStream({ + LocationAccuracy accuracy = LocationAccuracy.best, + int interval = 5000, + double distanceFilter = 0.0, + }) => + FlLocationPlatform.instance.getLocationStream( + accuracy: accuracy, + interval: interval, + distanceFilter: distanceFilter); + + /// Get the location services status stream. + static Stream getLocationServicesStatusStream() => + FlLocationPlatform.instance.getLocationServicesStatusStream(); +} diff --git a/third_party/pub_patches/fl_location/pubspec.yaml b/third_party/pub_patches/fl_location/pubspec.yaml new file mode 100644 index 000000000..b56f59a18 --- /dev/null +++ b/third_party/pub_patches/fl_location/pubspec.yaml @@ -0,0 +1,29 @@ +name: fl_location +description: A plugin that can access the location services of each platform and collect device location data. +homepage: https://github.com/Dev-hwang/flutter_location/tree/master/fl_location +version: 2.1.1 + +environment: + sdk: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" + +dependencies: + flutter: + sdk: flutter + fl_location_platform_interface: ^2.0.0 + fl_location_web: ^2.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + plugin: + platforms: + android: + package: com.pravera.fl_location + pluginClass: FlLocationPlugin + ios: + pluginClass: FlLocationPlugin + web: + default_package: fl_location_web diff --git a/third_party/pub_patches/fl_location/test/fl_location_test.dart b/third_party/pub_patches/fl_location/test/fl_location_test.dart new file mode 100644 index 000000000..153f05566 --- /dev/null +++ b/third_party/pub_patches/fl_location/test/fl_location_test.dart @@ -0,0 +1,3 @@ +void main() { + +} diff --git a/third_party/pub_patches/flutter_fgbg/CHANGELOG.md b/third_party/pub_patches/flutter_fgbg/CHANGELOG.md new file mode 100644 index 000000000..1d5b6d7ab --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/CHANGELOG.md @@ -0,0 +1,24 @@ +## 0.3.0 + +* Gradle 8 compatibility. Thanks @Rexios80 +* New `FGBGEvents.ignoreWhile` API + +## 0.2.2 + +* Move to mavenCentral + +## 0.2.1 + +* Fix use of FGBGNotifier and event stream in multiple places + +## 0.2.0 + +* Removed deprecated `registerWith` function to cleanup warnings + +## 0.1.0 + +* Null safety migration + +## 0.0.1 + +* Initial release. diff --git a/third_party/pub_patches/flutter_fgbg/LICENSE b/third_party/pub_patches/flutter_fgbg/LICENSE new file mode 100644 index 000000000..6fc5e040b --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Ajin Asokan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/third_party/pub_patches/flutter_fgbg/README.md b/third_party/pub_patches/flutter_fgbg/README.md new file mode 100644 index 000000000..ffbc2573e --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/README.md @@ -0,0 +1,60 @@ +# Flutter Foreground/Background Event Notifier + +Flutter plugin to detect when app(not Flutter container) goes to background or foreground. + +## Why + +Flutter has [WidgetsBindingObserver](https://api.flutter.dev/flutter/widgets/WidgetsBindingObserver-class.html) to get notified when app changes its state from active to inactive states and back. But it actually includes the state changes of the embedding Activity/ViewController as well. So if you have a plugin that opens a new activity/view controller or in iOS if you start a FaceID prompt then WidgetsBindingObserver will report as the app is inactive/resumed. + +This plugin on the other hand reports the events only at app level. Since most apps need only background/foreground events this plugin is implemented with just those events. In iOS, plugin reports `didEnterBackgroundNotification` and `willEnterForegroundNotification` notifications and in Android, plugin reports these using `androidx.lifecycle:lifecycle-process` package. + +Checkout `example/` project to see the differences in action. + +## Getting Started + +Add to your pubpsec: + +```shell +flutter pub add flutter_fgbg +``` + +Use the built in Widget: + +```dart +FGBGNotifier( + onEvent: (event) { + print(event); // FGBGType.foreground or FGBGType.background + }, + child: ..., +) +``` + +Or consume the event stream directly: + +```dart +import 'package:flutter_fgbg/flutter_fgbg.dart'; + +StreamSubscription subscription; + +... +// in initState +subscription = FGBGEvents.stream.listen((event) { + print(event); // FGBGType.foreground or FGBGType.background +}); + +// in dispose +subscription.cancel(); +``` + +## Caveats + +In newer Android versions and `image_picker` library, picking an image will open a different app this will make Flutter app switch to background/foreground and `flutter_fgbg` will report this. At the moment there is no solution to this since the API is working as intented. Tracking the issue [here](https://github.com/ajinasokan/flutter_fgbg/issues/5). + +As a work around you can use `FGBGEvents.ignoreWhile` API like this: + +```dart +FGBGEvents.ignoreWhile(() async { + await picker.pickImage(source: ImageSource.gallery); + // or do something else that can put app to background but don't want to be handled by flutter_fgbg +}); +``` diff --git a/third_party/pub_patches/flutter_fgbg/android/build.gradle b/third_party/pub_patches/flutter_fgbg/android/build.gradle new file mode 100644 index 000000000..c6f275157 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/android/build.gradle @@ -0,0 +1,38 @@ +group 'com.ajinasokan.flutter_fgbg' +version '1.0' + +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 36 + + defaultConfig { + minSdkVersion 16 + } + lintOptions { + disable 'InvalidPackage' + } + namespace "com.ajinasokan.flutter_fgbg" +} + +dependencies { + implementation 'androidx.lifecycle:lifecycle-process:2.2.0' +} diff --git a/third_party/pub_patches/flutter_fgbg/android/gradle.properties b/third_party/pub_patches/flutter_fgbg/android/gradle.properties new file mode 100644 index 000000000..38c8d4544 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/third_party/pub_patches/flutter_fgbg/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/flutter_fgbg/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..01a286e96 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/third_party/pub_patches/flutter_fgbg/android/settings.gradle b/third_party/pub_patches/flutter_fgbg/android/settings.gradle new file mode 100644 index 000000000..c8bd3d371 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'flutter_fgbg' diff --git a/third_party/pub_patches/flutter_fgbg/android/src/main/AndroidManifest.xml b/third_party/pub_patches/flutter_fgbg/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..63537af68 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/third_party/pub_patches/flutter_fgbg/android/src/main/java/com/ajinasokan/flutter_fgbg/FlutterFGBGPlugin.java b/third_party/pub_patches/flutter_fgbg/android/src/main/java/com/ajinasokan/flutter_fgbg/FlutterFGBGPlugin.java new file mode 100644 index 000000000..a949d7b4f --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/android/src/main/java/com/ajinasokan/flutter_fgbg/FlutterFGBGPlugin.java @@ -0,0 +1,67 @@ +package com.ajinasokan.flutter_fgbg; + + +import androidx.annotation.NonNull; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; +import androidx.lifecycle.ProcessLifecycleOwner; + +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.embedding.engine.plugins.activity.ActivityAware; +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; +import io.flutter.plugin.common.EventChannel; + +/** FlutterFGBGPlugin */ +public class FlutterFGBGPlugin implements FlutterPlugin, ActivityAware, LifecycleObserver, EventChannel.StreamHandler { + EventChannel.EventSink lifecycleSink; + + @Override + public void onListen(Object o, EventChannel.EventSink eventSink) { + lifecycleSink = eventSink; + } + + @Override + public void onCancel(Object o) { + lifecycleSink = null; + } + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { + new EventChannel(flutterPluginBinding.getBinaryMessenger(), "com.ajinasokan.flutter_fgbg/events") + .setStreamHandler(this); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {} + + @Override + public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { + ProcessLifecycleOwner.get().getLifecycle().addObserver(this); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + void onAppBackgrounded() { + if (lifecycleSink != null) { + lifecycleSink.success("background"); + } + } + + @OnLifecycleEvent(Lifecycle.Event.ON_START) + void onAppForegrounded() { + if (lifecycleSink != null) { + lifecycleSink.success("foreground"); + } + } + + @Override + public void onDetachedFromActivityForConfigChanges() {} + + @Override + public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {} + + @Override + public void onDetachedFromActivity() { + ProcessLifecycleOwner.get().getLifecycle().removeObserver(this); + } +} diff --git a/third_party/pub_patches/flutter_fgbg/example/README.md b/third_party/pub_patches/flutter_fgbg/example/README.md new file mode 100644 index 000000000..1e5963b8c --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/README.md @@ -0,0 +1,16 @@ +# flutter_fgbg_example + +Demonstrates how to use the flutter_fgbg plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/third_party/pub_patches/flutter_fgbg/example/analysis_options.yaml b/third_party/pub_patches/flutter_fgbg/example/analysis_options.yaml new file mode 100644 index 000000000..61b6c4de1 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/build.gradle b/third_party/pub_patches/flutter_fgbg/example/android/app/build.gradle new file mode 100644 index 000000000..d6cf152d1 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/build.gradle @@ -0,0 +1,56 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion flutter.compileSdkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.ajinasokan.example" + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/debug/AndroidManifest.xml b/third_party/pub_patches/flutter_fgbg/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..bce4beeb8 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/AndroidManifest.xml b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..d8b053a2c --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/java/com/ajinasokan/example/MainActivity.java b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/java/com/ajinasokan/example/MainActivity.java new file mode 100644 index 000000000..eee26c7d7 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/java/com/ajinasokan/example/MainActivity.java @@ -0,0 +1,7 @@ +package com.ajinasokan.example; + +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.android.FlutterFragmentActivity; + +public class MainActivity extends FlutterFragmentActivity { +} diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/drawable-v21/launch_background.xml b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/drawable/launch_background.xml b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..db77bb4b7 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..17987b79b Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09d439148 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5f1c8d34 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4d6372eeb Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/values-night/styles.xml b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..3db14bb53 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/values/styles.xml b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..d460d1e92 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/android/app/src/profile/AndroidManifest.xml b/third_party/pub_patches/flutter_fgbg/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..bce4beeb8 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/android/build.gradle b/third_party/pub_patches/flutter_fgbg/example/android/build.gradle new file mode 100644 index 000000000..4256f9173 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/third_party/pub_patches/flutter_fgbg/example/android/gradle.properties b/third_party/pub_patches/flutter_fgbg/example/android/gradle.properties new file mode 100644 index 000000000..94adc3a3f --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/third_party/pub_patches/flutter_fgbg/example/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/flutter_fgbg/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..bc6a58afd --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/third_party/pub_patches/flutter_fgbg/example/android/settings.gradle b/third_party/pub_patches/flutter_fgbg/example/android/settings.gradle new file mode 100644 index 000000000..44e62bcf0 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/AppFrameworkInfo.plist b/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..f2872cf47 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 9.0 + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/Debug.xcconfig b/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..e8efba114 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/Release.xcconfig b/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..399e9340e --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Podfile b/third_party/pub_patches/flutter_fgbg/example/ios/Podfile new file mode 100644 index 000000000..1e8c3c90a --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Podfile.lock b/third_party/pub_patches/flutter_fgbg/example/ios/Podfile.lock new file mode 100644 index 000000000..635bf7d3e --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Podfile.lock @@ -0,0 +1,34 @@ +PODS: + - Flutter (1.0.0) + - flutter_fgbg (0.0.1): + - Flutter + - image_picker (0.0.1): + - Flutter + - local_auth (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - flutter_fgbg (from `.symlinks/plugins/flutter_fgbg/ios`) + - image_picker (from `.symlinks/plugins/image_picker/ios`) + - local_auth (from `.symlinks/plugins/local_auth/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + flutter_fgbg: + :path: ".symlinks/plugins/flutter_fgbg/ios" + image_picker: + :path: ".symlinks/plugins/image_picker/ios" + local_auth: + :path: ".symlinks/plugins/local_auth/ios" + +SPEC CHECKSUMS: + Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + flutter_fgbg: 31c0d1140a131daea2d342121808f6aa0dcd879d + image_picker: 50e7c7ff960e5f58faa4d1f4af84a771c671bc4a + local_auth: ef62030a2731330b95df7ef1331bd15f6a64b8a6 + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.10.1 diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.pbxproj b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a9141eff7 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,583 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 9A00D670E6F367FE1519AC62 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B941493834C965DD20A6A502 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 25D318A4458E7A20BDDED965 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A961349DD7066D1AE7183DEB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + B941493834C965DD20A6A502 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F809CCBF8D4010BAD89EDC37 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9A00D670E6F367FE1519AC62 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1D990EAF64B7A96239E9C78E /* Frameworks */ = { + isa = PBXGroup; + children = ( + B941493834C965DD20A6A502 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + B96F73C090901BB9DB50CC54 /* Pods */, + 1D990EAF64B7A96239E9C78E /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + B96F73C090901BB9DB50CC54 /* Pods */ = { + isa = PBXGroup; + children = ( + F809CCBF8D4010BAD89EDC37 /* Pods-Runner.debug.xcconfig */, + A961349DD7066D1AE7183DEB /* Pods-Runner.release.xcconfig */, + 25D318A4458E7A20BDDED965 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 0DC4B0A3A8974CC2F1BCEDBF /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + D819938DB2643FC53019EC56 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0DC4B0A3A8974CC2F1BCEDBF /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + D819938DB2643FC53019EC56 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3634FUSGED; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.ajinasokan.flutterFgbgExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3634FUSGED; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.ajinasokan.flutterFgbgExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3634FUSGED; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.ajinasokan.flutterFgbgExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..a28140cfd --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/AppDelegate.swift b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..70693e4a8 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 000000000..dc9ada472 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 000000000..28c6bf030 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 000000000..f091b6b0b Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 000000000..4cde12118 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 000000000..d0ef06e7e Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 000000000..dcdc2306c Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 000000000..c8f9ed8f5 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 000000000..75b2d164a Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 000000000..c4df70d39 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 000000000..6a84f41e1 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 000000000..d0e1f5853 Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000..0bedcf2fd --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Base.lproj/Main.storyboard b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Info.plist b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Info.plist new file mode 100644 index 000000000..0fdce28e8 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Info.plist @@ -0,0 +1,53 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + flutter_fgbg_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + NSFaceIDUsageDescription + Just testing + NSPhotoLibraryUsageDescription + Just testing + NSCameraUsageDescription + Just testing + NSMicrophoneUsageDescription + Just testing + + diff --git a/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Runner-Bridging-Header.h b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..308a2a560 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/third_party/pub_patches/flutter_fgbg/example/lib/main.dart b/third_party/pub_patches/flutter_fgbg/example/lib/main.dart new file mode 100644 index 000000000..e3aa45dba --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/lib/main.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_fgbg/flutter_fgbg.dart'; +import 'package:local_auth/local_auth.dart'; +import 'package:image_picker/image_picker.dart'; + +void main() { + runApp(MyApp()); +} + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State with WidgetsBindingObserver { + final picker = ImagePicker(); + + List events = []; + + void didChangeAppLifecycleState(AppLifecycleState state) { + events.add(state.toString()); + setState(() {}); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + Widget build(BuildContext context) { + return FGBGNotifier( + onEvent: (event) { + events.add(event.toString()); + setState(() {}); + }, + child: MaterialApp( + home: Scaffold( + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ElevatedButton( + onPressed: () { + events.clear(); + setState(() {}); + }, + child: Text("Clear logs"), + ), + ElevatedButton( + onPressed: () async { + events.add("// Opening camera"); + setState(() {}); + await picker.pickImage(source: ImageSource.camera); + }, + child: Text("Take Image"), + ), + ElevatedButton( + onPressed: () async { + events.add("// Opening gallery"); + setState(() {}); + await picker.pickImage(source: ImageSource.gallery); + }, + child: Text("Pick Image"), + ), + ElevatedButton( + onPressed: () async { + events.add( + "// Opening camera but ignoring events during this"); + setState(() {}); + FGBGEvents.ignoreWhile(() async { + await picker.pickImage(source: ImageSource.camera); + }); + }, + child: Text("Take Image ignoreWhile"), + ), + ElevatedButton( + onPressed: () async { + events.add( + "// Opening gallery but ignoring events during this"); + setState(() {}); + + FGBGEvents.ignoreWhile(() async { + await picker.pickImage(source: ImageSource.gallery); + }); + }, + child: Text("Pick Image ignoreWhile"), + ), + ElevatedButton( + onPressed: () async { + events.add("// Prompting biometric"); + setState(() {}); + var auth = LocalAuthentication(); + + await auth.authenticate( + // biometricOnly: true, + options: AuthenticationOptions( + biometricOnly: true, + ), + localizedReason: 'Test', + ); + }, + child: Text("FaceID"), + ), + SizedBox(height: 16), + Expanded( + child: ListView( + children: [for (var e in events) Text(e)], + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/third_party/pub_patches/flutter_fgbg/example/pubspec.yaml b/third_party/pub_patches/flutter_fgbg/example/pubspec.yaml new file mode 100644 index 000000000..8a33cf649 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/pubspec.yaml @@ -0,0 +1,71 @@ +name: flutter_fgbg_example +description: Demonstrates how to use the flutter_fgbg plugin. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: "none" # Remove this line if you wish to publish to pub.dev + +environment: + sdk: ">=2.12.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + local_auth: 2.1.6 + image_picker: 0.8.7+1 + flutter_fgbg: + # When depending on this package from a real application you should use: + # flutter_fgbg: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: 1.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/third_party/pub_patches/flutter_fgbg/example/test/widget_test.dart b/third_party/pub_patches/flutter_fgbg/example/test/widget_test.dart new file mode 100644 index 000000000..2f0f9724f --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flutter_fgbg_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/third_party/pub_patches/flutter_fgbg/ios/Classes/FlutterFGBGPlugin.h b/third_party/pub_patches/flutter_fgbg/ios/Classes/FlutterFGBGPlugin.h new file mode 100644 index 000000000..771700bea --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/ios/Classes/FlutterFGBGPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FlutterFGBGPlugin : NSObject +@end diff --git a/third_party/pub_patches/flutter_fgbg/ios/Classes/FlutterFGBGPlugin.m b/third_party/pub_patches/flutter_fgbg/ios/Classes/FlutterFGBGPlugin.m new file mode 100644 index 000000000..5f34edc0d --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/ios/Classes/FlutterFGBGPlugin.m @@ -0,0 +1,15 @@ +#import "FlutterFGBGPlugin.h" +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "flutter_fgbg-Swift.h" +#endif + +@implementation FlutterFGBGPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftFlutterFGBGPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/third_party/pub_patches/flutter_fgbg/ios/Classes/SwiftFlutterFgbgPlugin.swift b/third_party/pub_patches/flutter_fgbg/ios/Classes/SwiftFlutterFgbgPlugin.swift new file mode 100644 index 000000000..3a5103b27 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/ios/Classes/SwiftFlutterFgbgPlugin.swift @@ -0,0 +1,45 @@ +import UIKit +import Flutter +import UserNotifications + +public class SwiftFlutterFGBGPlugin: NSObject, FlutterPlugin, FlutterStreamHandler { + private var eventSink: FlutterEventSink? + + public static func register(with registrar: FlutterPluginRegistrar) { + let instance = SwiftFlutterFGBGPlugin() + + let lifeCycleChannel = "com.ajinasokan.flutter_fgbg/events" + let lifecycleEventChannel = FlutterEventChannel(name: lifeCycleChannel, binaryMessenger: registrar.messenger()) + lifecycleEventChannel.setStreamHandler(instance as FlutterStreamHandler & NSObjectProtocol) + + let notificationCenter = NotificationCenter.default + notificationCenter.addObserver(instance, + selector: #selector(didEnterBackground), + name: UIApplication.didEnterBackgroundNotification, + object: nil) + + notificationCenter.addObserver(instance, + selector: #selector(willEnterForeground), + name: UIApplication.willEnterForegroundNotification, + object: nil) + } + + public func onListen(withArguments arguments: Any?, + eventSink: @escaping FlutterEventSink) -> FlutterError? { + self.eventSink = eventSink + return nil + } + + public func onCancel(withArguments arguments: Any?) -> FlutterError? { + eventSink = nil + return nil + } + + @objc func didEnterBackground() { + self.eventSink?("background") + } + + @objc func willEnterForeground() { + self.eventSink?("foreground") + } +} diff --git a/third_party/pub_patches/flutter_fgbg/ios/flutter_fgbg.podspec b/third_party/pub_patches/flutter_fgbg/ios/flutter_fgbg.podspec new file mode 100644 index 000000000..890967981 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/ios/flutter_fgbg.podspec @@ -0,0 +1,23 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint flutter_fgbg.podspec' to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'flutter_fgbg' + s.version = '0.0.1' + s.summary = 'Flutter plugin to detect when app(not Flutter container) goes to background or foreground' + s.description = <<-DESC +Flutter plugin to detect when app(not Flutter container) goes to background or foreground + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '8.0' + + # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } + s.swift_version = '5.0' +end diff --git a/third_party/pub_patches/flutter_fgbg/lib/flutter_fgbg.dart b/third_party/pub_patches/flutter_fgbg/lib/flutter_fgbg.dart new file mode 100644 index 000000000..393b449b3 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/lib/flutter_fgbg.dart @@ -0,0 +1,69 @@ +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; + +enum FGBGType { + foreground, + background, +} + +class FGBGEvents { + static const _channel = EventChannel("com.ajinasokan.flutter_fgbg/events"); + static Stream? _stream; + + static Stream get stream { + return _stream ??= _channel + .receiveBroadcastStream() + .where((_) => !_ignoreEvent) + .map((e) => + e == "foreground" ? FGBGType.foreground : FGBGType.background); + } + + static bool _ignoreEvent = false; + static void ignoreWhile(dynamic Function() closure) async { + _ignoreEvent = true; + try { + final result = closure(); + if (result is Future) await result; + } catch (e) { + _ignoreEvent = false; + rethrow; + } + _ignoreEvent = false; + } +} + +class FGBGNotifier extends StatefulWidget { + final Widget child; + final ValueChanged onEvent; + + FGBGNotifier({ + required this.child, + required this.onEvent, + }); + + @override + _FGBGNotifierState createState() => _FGBGNotifierState(); +} + +class _FGBGNotifierState extends State { + StreamSubscription? subscription; + + @override + void initState() { + super.initState(); + subscription = FGBGEvents.stream.listen((event) { + widget.onEvent.call(event); + }); + } + + @override + void dispose() { + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) => widget.child; +} diff --git a/third_party/pub_patches/flutter_fgbg/pubspec.yaml b/third_party/pub_patches/flutter_fgbg/pubspec.yaml new file mode 100644 index 000000000..6bffacbb2 --- /dev/null +++ b/third_party/pub_patches/flutter_fgbg/pubspec.yaml @@ -0,0 +1,64 @@ +name: flutter_fgbg +description: Flutter plugin to detect when app(not Flutter container) goes to background or foreground +version: 0.3.0 +homepage: https://github.com/ajinasokan/flutter_fgbg + +environment: + sdk: ">=2.12.0 <3.0.0" + flutter: ">=1.12.13+hotfix.6" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' and Android 'package' identifiers should not ordinarily + # be modified. They are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + android: + package: com.ajinasokan.flutter_fgbg + pluginClass: FlutterFGBGPlugin + ios: + pluginClass: FlutterFGBGPlugin + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/third_party/pub_patches/fluttertoast/CHANGELOG.md b/third_party/pub_patches/fluttertoast/CHANGELOG.md new file mode 100644 index 000000000..c7ffdf4f4 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/CHANGELOG.md @@ -0,0 +1,338 @@ +## [8.2.8] + +- Merged multiple PRs thanks for your contributions + +## [8.2.6] + +- Merged PR #507 - Migrating dart:html to package:web thanks to @a-h-mzd for PR + +## [8.2.5] + +- Merged multiple PRs #492 #490 #489 #480 - Thanks to all contributors + +## [8.2.4] + +- Reverted the minSDK 22 which broke many apps - Sorry everyone + +## [8.2.3] + +- Merged PR #466 (fixes issue in android) + +## [8.2.2] + +- Adjustments for flutter >=3.10 + +## [8.2.1] + +- Removed `context.mounted` + +## [8.2.0] + +- Updated the flow for Toast with Context + +## [8.1.4] + +- Merged #419 (added environment restriction in pubspec) + +## [8.1.3] + +- Merged #415 (improvements to provide safer usage) @AlexSeednov +- Updated Readme.md + +## [8.1.2] + +- Merged #405 #408 + +## [8.1.1] [8.1.0] + +- Many issues fixed +- iOS M1 Chip Fix + +## [8.0.9] + +- Merged PRS #342 #353 #363 #346 and #370 + +## [8.0.8] + +- Many issues fixed + +## [8.0.7] + +- Added fadeDuration in FToast to set fade animation Duration +- Fixed Toast behind the screen #287 , #281 +- Fixed #303 +## [8.0.6] + +- Only safe (?.) or non-null asserted (!!.) (#300) + +## [8.0.5] + +- Fixed Unresolved reference: R (Issue with Android API 30) +## [8.0.4] + +- Fixed Unresolved reference: R (Issue with Android API 30) + +## [8.0.3] + +- flutter analyze fixes + +## [8.0.2] + +- Null Safety +- Code Docs Added + +## [7.1.8] + +- Web sourceMap Warning + +## [7.1.7] + +- '\n' line crash on Web PR Merged +- Android 11 Crash fixed +- Many bug fixes + +## [7.1.6] + +- minor fixes + +## [7.1.4] + +- minor fixes + +## [7.1.3] + +- Android Default bg when fontSize or textColor set fixed + +## [7.1.2] + +- Android Rounded Corners fix (#238) +- Android Crash if cancel called before init (#231) +- Web now load js & css from assets +- Web SyntaxError if Toast msg has `'` fixed + +## [7.1.1] + +- iOS Unused variables fix + +## [7.1.0] + +- Breaking change for FToast, Need to call `FToast.init(context)` before `showToast` +- AnimationController fix +- Android `NonNull` build Fix +- FToast Added new `PositionedToastBuilder` you can define Custom Postition now for toast +- Merged #228, Fix UIView+Toast.o duplicate symbols - Thanks @jackkang0401 and @yongshuai.kang +- Now `textcolor` will work for web toast + +## [7.0.4] + +- iOS Build Failed Fixed #218 +- Fixed Cancel Toasts in iOS + +## [7.0.3] + +- FToast now Fade when showing and hiding the toast +- Toast backgroud now supports transparency +- Bug fixes + +## [7.0.2] + +- iOS Toast behind keyboard fixed. #203 + +## [7.0.1+1] + +- Readme Updated + +## [7.0.1] + +- Android Build failed fix +- iOS Crash Fix + +## [7.0.0] + +- Reverted to Old code `Fluttertoast` +- Also contains new code `FToast` + +## [6.0.1] + +- Support for old `Fluttertoast.showToast` + +## [6.0.0] + +- Complete new package +- Now plugin dont use any native code + +## [5.0.2] + +- Web Fix after name change + + +## [5.0.1] + +- Many things changes on android side (this will break your current implementation) +- `Fluttertoast.` to `FlutterToast.` +- many fixes + +## [4.0.2] + +- Delete print on fluttertoast_web + +## [4.0.1] + +- ReadMe Fixes + +## [4.0.0] + +- Added Web Support + +## [3.1.3] + +- Toast optimized for Android + +## [3.1.2] + +- Flutter analysis failed fixed + +## [3.1.1] + +- Not Compiling in android (issue with AndroidX) + +## [3.1.0] + +- Migrated to AndroidX + +##[3.0.6] + +- iOS build failed fixed + +## [3.0.5] + +- deprecation fixed +- hope ios notch fixed + +## [3.0.4] + +- Android Color fix + +## [3.0.3] + +- fixed Android Toast.LENGTH\_\* + +## [3.0.2] + +- fixed #70 #71 + +## [3.0.1] + +- Release build failed fix +- Multiline text android fix + +## [3.0.0] + +- Migrated to AndroidX + +## [2.2.12] + +- Incomplete Text Fix + +## [2.2.11] + +- Incomplete Text Fix + +## [2.2.10] + +- iOS build Failed fix + +## [2.2.9] + +- iOS build Failed fix + +## [2.2.8] + +- `Fluttertoast.cancel()` added +- FlutterToast Implementation revert back to previous + +## [2.2.7] + +- FontSize Can be changed +- FlutterToast Implementation Changed to `FlutterToast.instance` + +## [2.2.6] + +- removed androidx + +## [2.2.5] + +- Cannot build because of dependency w/ v28 #47 + +## [2.2.4] + +- androidX crash fix #45 + +## [2.2.3] + +- iOS Crash fix #41 & #39 + +## [2.2.1] + +- default toast style fix #38 + +## [2.2.0] + +- Background color fixed #29 + +## [2.1.5] + +- Merged PR #36 - Fix Number Cast Error for issue #35 + +## [2.1.4] + +- Merged PR #32 + +## [2.1.2] + +- iOS Color Fix +- Background color fix in PIE + +## [2.1.1] + +- Background color does not fill the whole Toast fixed + +## [2.1.0] + +- build error fixed + +## [2.0.9] + +- fix error in flutter 0.9.7 + +## [2.0.8] + +- Build failed with an exception fixed +- The plugin calls the build of the previous widget fixed +- Screenshots added + +## [2.0.7] + +- Text background fix for android + +## [2.0.6] + +- iOS Release build error fixed + +## [2.0.3] + +- iOs run time error fixed + +## [2.0.2] + +- iOs build error fixed + +## [2.0.1] + +- Ios Support added +- option for setting toast gravity (top, center, bottom) + +## [1.0.1] + +- Initial Open Sources +- show Toast in Android diff --git a/third_party/pub_patches/fluttertoast/CONTRIBUTING.md b/third_party/pub_patches/fluttertoast/CONTRIBUTING.md new file mode 100644 index 000000000..a1d8c668d --- /dev/null +++ b/third_party/pub_patches/fluttertoast/CONTRIBUTING.md @@ -0,0 +1,22 @@ +# Contributing + +Awesome! Contributions of all kinds are greatly appreciated. To help smoothen the process we have a few non-exhaustive guidelines to follow which should get you going in no time. + +## Using GitHub Issues + +- Feel free to use GitHub issues for questions, bug reports, and feature requests +- Use the search feature to check for an existing issue +- Include as much information as possible and provide any relevant resources (Eg. screenshots) +- For bug reports ensure you have a reproducible test case + - A pull request with a breaking test would be super preferable here but isn't required + +## Getting Started +- Fork the repository +- Send your commits +- Submit a Pull request + +## Submitting a Pull Request +- Write appropriate title +- Wrtie a proper description including the issue name and solution + + diff --git a/third_party/pub_patches/fluttertoast/LICENSE b/third_party/pub_patches/fluttertoast/LICENSE new file mode 100644 index 000000000..26d032e2f --- /dev/null +++ b/third_party/pub_patches/fluttertoast/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Karthik Ponnam + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/pub_patches/fluttertoast/README.md b/third_party/pub_patches/fluttertoast/README.md new file mode 100644 index 000000000..1395f76a2 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/README.md @@ -0,0 +1,234 @@ + +# [fluttertoast](https://pub.dev/packages/fluttertoast) + +Toast Library for Flutter + +![Build Checks](https://github.com/ponnamkarthik/FlutterToast/workflows/Build%20Checks/badge.svg) + +Now this toast library supports two kinds of toast messages one which requires `BuildContext` other with No `BuildContext` + +## Toast with no context + +> Supported Platforms +> +> - Android +> - IOS +> - Web (Uses [Toastify-JS](https://github.com/apvarun/toastify-js)) + +This one has limited features and no control over UI + + +## Toast Which requires BuildContext + +> Supported Platforms +> +> - ALL + +1. Full Control of the Toast +2. Toasts will be queued +3. Remove a toast +4. Clear the queue + + +## How to Use + +```yaml +# add this line to your dependencies +fluttertoast: ^8.2.8 +``` + +```dart +import 'package:fluttertoast/fluttertoast.dart'; +``` + +## Toast with No Build Context (Android & iOS) + +```dart +Fluttertoast.showToast( + msg: "This is Center Short Toast", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 1, + backgroundColor: Colors.red, + textColor: Colors.white, + fontSize: 16.0 + ); +``` + +| property | description | default | +| --------------- | ------------------------------------------------------------------ |------------| +| msg | String (Not Null)(required) |required | +| toastLength | Toast.LENGTH_SHORT or Toast.LENGTH_LONG (optional) |Toast.LENGTH_SHORT | +| gravity | ToastGravity.TOP (or) ToastGravity.CENTER (or) ToastGravity.BOTTOM (Web Only supports top, bottom) | ToastGravity.BOTTOM | +| timeInSecForIosWeb | int (for ios & web) | 1 (sec) | +| backgroundColor | Colors.red |null | +| textcolor | Colors.white |null | +| fontSize | 16.0 (float) | null | +| fontAsset | Path to a font file in the Flutter app assets folder, e.g. 'assets/path/to/some-font.ttf' (String) | null | +| webShowClose | false (bool) | false | +| webBgColor | String (hex Color) | linear-gradient(to right, #00b09b, #96c93d) | +| webPosition | String (`left`, `center` or `right`) | right | + +### To cancel all the toasts call + +```dart +Fluttertoast.cancel() +``` + +### Note Android + + + + +> Custom Toast will not work on android 11 and above, it will only use *msg* and *toastLength* remaining all properties are ignored + + +### Custom Toast For Android + +Create a file named `toast_custom.xml` in your project `app/res/layout` folder and do custom styling + +```xml + + + + + +``` + +## Toast with BuildContext (All Platforms) + +Update your `MaterialApp` with `builder` like below for the use of Context globally check doc section Use NavigatorKey for Context(to access context globally) + +```dart +MaterialApp( + builder: FToastBuilder(), + home: MyApp(), + navigatorKey: navigatorKey, +), +``` + +```dart +FToast fToast; + +@override +void initState() { + super.initState(); + fToast = FToast(); + // if you want to use context from globally instead of content we need to pass navigatorKey.currentContext! + fToast.init(context); +} + +_showToast() { + Widget toast = Container( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25.0), + color: Colors.greenAccent, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.check), + SizedBox( + width: 12.0, + ), + Text("This is a Custom Toast"), + ], + ), + ); + + + fToast.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + ); + + // Custom Toast Position + fToast.showToast( + child: toast, + toastDuration: Duration(seconds: 2), + positionedToastBuilder: (context, child) { + return Positioned( + child: child, + top: 16.0, + left: 16.0, + ); + }); +} + +``` + +Now Call `_showToast()` + +For more details check `example` project + +| property | description | default | +| --------------- | ------------------------------------------------------------------ |------------| +| child | Widget (Not Null)(required) |required | +| toastDuration | Duration (optional) | | +| gravity | ToastGravity.* | | + +### Use NavigatorKey for Context(to access context globally) + +To use NavigatorKey for Context first define the `GlobalKey` at top level in your `main.dart` file + +```dart +GlobalKey navigatorKey = GlobalKey(); +``` + +At the time of initializing the `FToast` we need to use context from globally defined `GlobalKey` + +```dart +FToast fToast = FToast(); +fToast.init(yourNavKey.currentContext!); +``` + +### To cancel all the toasts call + +```dart +// To remove present shwoing toast +fToast.removeCustomToast() + +// To clear the queue +fToast.removeQueuedCustomToasts(); +``` + +## Preview Images (No BuildContext) + + + + + + +## Preview Images (BuildContext) + + + + +## If you need any features suggest + +... + + +## Buy Me a Coffee + +Buy Me A Coffee diff --git a/third_party/pub_patches/fluttertoast/android/build.gradle b/third_party/pub_patches/fluttertoast/android/build.gradle new file mode 100644 index 000000000..0be8fd5d0 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/build.gradle @@ -0,0 +1,59 @@ +group 'com.example.FlutterToast' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.0' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.3' + //noinspection GradleDependency + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 33 + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = '11' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + minSdkVersion 19 + targetSdkVersion 33 + if (project.android.hasProperty('namespace')) { + namespace 'io.github.ponnamkarthik.toast.fluttertoast' + } + } + + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/third_party/pub_patches/fluttertoast/android/gradle.properties b/third_party/pub_patches/fluttertoast/android/gradle.properties new file mode 100644 index 000000000..94adc3a3f --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/third_party/pub_patches/fluttertoast/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/fluttertoast/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..595fb867a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip diff --git a/third_party/pub_patches/fluttertoast/android/settings.gradle b/third_party/pub_patches/fluttertoast/android/settings.gradle new file mode 100644 index 000000000..c68c12ec0 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'FlutterToast' diff --git a/third_party/pub_patches/fluttertoast/android/src/main/AndroidManifest.xml b/third_party/pub_patches/fluttertoast/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..e68b9d7b0 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/third_party/pub_patches/fluttertoast/android/src/main/kotlin/io/github/ponnamkarthik/toast/fluttertoast/FlutterToastPlugin.kt b/third_party/pub_patches/fluttertoast/android/src/main/kotlin/io/github/ponnamkarthik/toast/fluttertoast/FlutterToastPlugin.kt new file mode 100644 index 000000000..e660fe415 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/src/main/kotlin/io/github/ponnamkarthik/toast/fluttertoast/FlutterToastPlugin.kt @@ -0,0 +1,33 @@ +package io.github.ponnamkarthik.toast.fluttertoast + +import android.content.Context +import androidx.annotation.NonNull +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +/** FlutterToastPlugin */ +public class FlutterToastPlugin: FlutterPlugin { + + private var channel: MethodChannel? = null + + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding,) { + setupChannel(binding.binaryMessenger, binding.applicationContext,) + } + + override fun onDetachedFromEngine(p0: FlutterPlugin.FlutterPluginBinding,) { + teardownChannel(); + } + + private fun setupChannel(messenger: BinaryMessenger, context: Context,) { + channel = MethodChannel(messenger, "PonnamKarthik/fluttertoast",) + val handler = MethodCallHandlerImpl(context,) + channel?.setMethodCallHandler(handler,) + } + + private fun teardownChannel() { + channel?.setMethodCallHandler(null,) + channel = null + } + +} diff --git a/third_party/pub_patches/fluttertoast/android/src/main/kotlin/io/github/ponnamkarthik/toast/fluttertoast/MethodCallHandlerImpl.kt b/third_party/pub_patches/fluttertoast/android/src/main/kotlin/io/github/ponnamkarthik/toast/fluttertoast/MethodCallHandlerImpl.kt new file mode 100644 index 000000000..c15d35f56 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/src/main/kotlin/io/github/ponnamkarthik/toast/fluttertoast/MethodCallHandlerImpl.kt @@ -0,0 +1,138 @@ +package io.github.ponnamkarthik.toast.fluttertoast + +import android.app.Activity +import android.content.Context +import android.content.res.AssetManager +import android.graphics.PorterDuff +import android.graphics.Typeface +import android.graphics.drawable.Drawable +import android.os.Build +import android.view.Gravity +import android.view.LayoutInflater +import android.widget.TextView +import android.widget.Toast +import androidx.core.content.ContextCompat +import io.flutter.FlutterInjector +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import java.io.File + +internal class MethodCallHandlerImpl(private var context: Context) : MethodCallHandler { + + private var mToast: Toast? = null + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result,) { + when (call.method) { + "showToast" -> { + val mMessage = call.argument("msg").toString() + val length = call.argument("length").toString() + val gravity = call.argument("gravity").toString() + val bgcolor = call.argument("bgcolor") + val textcolor = call.argument("textcolor") + val fontSize = call.argument("fontSize") + val fontAsset = call.argument("fontAsset") + + val mGravity: Int = when (gravity) { + "top" -> Gravity.TOP + "center" -> Gravity.CENTER + else -> Gravity.BOTTOM + } + + val mDuration: Int = if (length == "long") { + Toast.LENGTH_LONG + } else { + Toast.LENGTH_SHORT + } + + if (bgcolor != null) { + val layout = (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE,) as LayoutInflater).inflate(R.layout.toast_custom, null,) + val text = layout.findViewById(R.id.text,) + text.text = mMessage + + val gradientDrawable: Drawable? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + context.getDrawable(R.drawable.corner)!! + } else { + // context.resources.getDrawable(R.drawable.corner) + ContextCompat.getDrawable(context, R.drawable.corner) + } + gradientDrawable!!.setColorFilter(bgcolor.toInt(), PorterDuff.Mode.SRC_IN) + text.background = gradientDrawable + + if (fontSize != null) { + text.textSize = fontSize.toFloat() + } + if (textcolor != null) { + text.setTextColor(textcolor.toInt()) + } + + mToast = Toast(context,) + mToast?.duration = mDuration + + if (fontAsset != null) { + val assetManager: AssetManager = context.assets + val key = FlutterInjector.instance().flutterLoader().getLookupKeyForAsset(fontAsset) + text.typeface = Typeface.createFromAsset(assetManager, key); + } + mToast?.view = layout + } else { + mToast = Toast.makeText(context, mMessage, mDuration) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + val textView: TextView = mToast?.view!!.findViewById(android.R.id.message) + if (fontSize != null) { + textView.textSize = fontSize.toFloat() + } + if (textcolor != null) { + textView.setTextColor(textcolor.toInt()) + } + if (fontAsset != null) { + val assetManager: AssetManager = context.assets + val key = FlutterInjector.instance().flutterLoader().getLookupKeyForAsset(fontAsset) + textView.typeface = Typeface.createFromAsset(assetManager, key); + } + } + } + + try { + when (mGravity) { + Gravity.CENTER -> { + mToast?.setGravity(mGravity, 0, 0,) + } + Gravity.TOP -> { + mToast?.setGravity(mGravity, 0, 100,) + } + else -> { + mToast?.setGravity(mGravity, 0, 100,) + } + } + } catch (e: Exception,) { } + + if (context is Activity) { + (context as Activity).runOnUiThread { mToast?.show() } + } else { + mToast?.show() + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + mToast?.addCallback( + object : Toast.Callback() { + override fun onToastHidden() { + super.onToastHidden() + mToast = null + } + }, + ) + } + result.success(true,) + } + "cancel" -> { + if (mToast != null) { + mToast?.cancel() + mToast = null + } + result.success(true,) + } + else -> result.notImplemented() + } + } +} diff --git a/third_party/pub_patches/fluttertoast/android/src/main/res/drawable/corner.xml b/third_party/pub_patches/fluttertoast/android/src/main/res/drawable/corner.xml new file mode 100644 index 000000000..341a7119a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/src/main/res/drawable/corner.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/third_party/pub_patches/fluttertoast/android/src/main/res/drawable/toast_bg.xml b/third_party/pub_patches/fluttertoast/android/src/main/res/drawable/toast_bg.xml new file mode 100644 index 000000000..6c99b3100 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/src/main/res/drawable/toast_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/third_party/pub_patches/fluttertoast/android/src/main/res/layout/toast_custom.xml b/third_party/pub_patches/fluttertoast/android/src/main/res/layout/toast_custom.xml new file mode 100644 index 000000000..e24c63daf --- /dev/null +++ b/third_party/pub_patches/fluttertoast/android/src/main/res/layout/toast_custom.xml @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/third_party/pub_patches/fluttertoast/assets/toastify.css b/third_party/pub_patches/fluttertoast/assets/toastify.css new file mode 100644 index 000000000..2d0471ef9 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/assets/toastify.css @@ -0,0 +1,14 @@ +/** + * Minified by jsDelivr using clean-css v4.2.3. + * Original file: /npm/toastify-js@1.9.3/src/toastify.css + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! + * Toastify js 1.9.3 + * https://github.com/apvarun/toastify-js + * @license MIT licensed + * + * Copyright (C) 2018 Varun A P + */ +.toastify{padding:12px 20px;color:#fff;display:inline-block;box-shadow:0 3px 6px -1px rgba(0,0,0,.12),0 10px 36px -4px rgba(77,96,232,.3);background:-webkit-linear-gradient(315deg,#73a5ff,#5477f5);background:linear-gradient(135deg,#73a5ff,#5477f5);position:fixed;opacity:0;transition:all .4s cubic-bezier(.215,.61,.355,1);border-radius:2px;cursor:pointer;text-decoration:none;max-width:calc(50% - 20px);z-index:2147483647}.toastify.on{opacity:1}.toast-close{opacity:.4;padding:0 5px}.toastify-right{right:15px}.toastify-left{left:15px}.toastify-top{top:-150px}.toastify-bottom{bottom:-150px}.toastify-rounded{border-radius:25px}.toastify-avatar{width:1.5em;height:1.5em;margin:-7px 5px;border-radius:2px}.toastify-center{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content;max-width:-moz-fit-content}@media only screen and (max-width:360px){.toastify-left,.toastify-right{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content}} \ No newline at end of file diff --git a/third_party/pub_patches/fluttertoast/assets/toastify.js b/third_party/pub_patches/fluttertoast/assets/toastify.js new file mode 100644 index 000000000..3bb0860a0 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/assets/toastify.js @@ -0,0 +1,14 @@ +/** + * Minified by jsDelivr using Terser v5.3.0. + * Original file: /npm/toastify-js@1.9.3/src/toastify.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! + * Toastify js 1.9.3 + * https://github.com/apvarun/toastify-js + * @license MIT licensed + * + * Copyright (C) 2018 Varun A P + */ +!function(t,o){"object"==typeof module && module && module.exports?module.exports=o():t.Toastify=o()}(this,(function(t){var o=function(t){return new o.lib.init(t)};function i(t,o){return o.offset[t]?isNaN(o.offset[t])?o.offset[t]:o.offset[t]+"px":"0px"}function s(t,o){return!(!t||"string"!=typeof o)&&!!(t.className&&t.className.trim().split(/\s+/gi).indexOf(o)>-1)}return o.lib=o.prototype={toastify:"1.9.3",constructor:o,init:function(t){return t||(t={}),this.options={},this.toastElement=null,this.options.text=t.text||"Hi there!",this.options.node=t.node,this.options.duration=0===t.duration?0:t.duration||3e3,this.options.selector=t.selector,this.options.callback=t.callback||function(){},this.options.destination=t.destination,this.options.newWindow=t.newWindow||!1,this.options.close=t.close||!1,this.options.gravity="bottom"===t.gravity?"toastify-bottom":"toastify-top",this.options.positionLeft=t.positionLeft||!1,this.options.position=t.position||"",this.options.backgroundColor=t.backgroundColor,this.options.avatar=t.avatar||"",this.options.className=t.className||"",this.options.stopOnFocus=void 0===t.stopOnFocus||t.stopOnFocus,this.options.onClick=t.onClick,this.options.offset=t.offset||{x:0,y:0},this},buildToast:function(){if(!this.options)throw"Toastify is not initialized";var t=document.createElement("div");if(t.className="toastify on "+this.options.className,this.options.position?t.className+=" toastify-"+this.options.position:!0===this.options.positionLeft?(t.className+=" toastify-left",console.warn("Property `positionLeft` will be depreciated in further versions. Please use `position` instead.")):t.className+=" toastify-right",t.className+=" "+this.options.gravity,this.options.backgroundColor&&(t.style.background=this.options.backgroundColor),this.options.node&&this.options.node.nodeType===Node.ELEMENT_NODE)t.appendChild(this.options.node);else if(t.innerHTML=this.options.text,""!==this.options.avatar){var o=document.createElement("img");o.src=this.options.avatar,o.className="toastify-avatar","left"==this.options.position||!0===this.options.positionLeft?t.appendChild(o):t.insertAdjacentElement("afterbegin",o)}if(!0===this.options.close){var s=document.createElement("span");s.innerHTML="✖",s.className="toast-close",s.addEventListener("click",function(t){t.stopPropagation(),this.removeElement(this.toastElement),window.clearTimeout(this.toastElement.timeOutValue)}.bind(this));var n=window.innerWidth>0?window.innerWidth:screen.width;("left"==this.options.position||!0===this.options.positionLeft)&&n>360?t.insertAdjacentElement("afterbegin",s):t.appendChild(s)}if(this.options.stopOnFocus&&this.options.duration>0){var e=this;t.addEventListener("mouseover",(function(o){window.clearTimeout(t.timeOutValue)})),t.addEventListener("mouseleave",(function(){t.timeOutValue=window.setTimeout((function(){e.removeElement(t)}),e.options.duration)}))}if(void 0!==this.options.destination&&t.addEventListener("click",function(t){t.stopPropagation(),!0===this.options.newWindow?window.open(this.options.destination,"_blank"):window.location=this.options.destination}.bind(this)),"function"==typeof this.options.onClick&&void 0===this.options.destination&&t.addEventListener("click",function(t){t.stopPropagation(),this.options.onClick()}.bind(this)),"object"==typeof this.options.offset){var a=i("x",this.options),p=i("y",this.options),r="left"==this.options.position?a:"-"+a,l="toastify-top"==this.options.gravity?p:"-"+p;t.style.transform="translate("+r+","+l+")"}return t},showToast:function(){var t;if(this.toastElement=this.buildToast(),!(t=void 0===this.options.selector?document.body:document.getElementById(this.options.selector)))throw"Root element is not defined";return t.insertBefore(this.toastElement,t.firstChild),o.reposition(),this.options.duration>0&&(this.toastElement.timeOutValue=window.setTimeout(function(){this.removeElement(this.toastElement)}.bind(this),this.options.duration)),this},hideToast:function(){this.toastElement.timeOutValue&&clearTimeout(this.toastElement.timeOutValue),this.removeElement(this.toastElement)},removeElement:function(t){t.className=t.className.replace(" on",""),window.setTimeout(function(){this.options.node&&this.options.node.parentNode&&this.options.node.parentNode.removeChild(this.options.node),t.parentNode&&t.parentNode.removeChild(t),this.options.callback.call(t),o.reposition()}.bind(this),400)}},o.reposition=function(){for(var t,o={top:15,bottom:15},i={top:15,bottom:15},n={top:15,bottom:15},e=document.getElementsByClassName("toastify"),a=0;a0?window.innerWidth:screen.width)<=360?(e[a].style[t]=n[t]+"px",n[t]+=p+15):!0===s(e[a],"toastify-left")?(e[a].style[t]=o[t]+"px",o[t]+=p+15):(e[a].style[t]=i[t]+"px",i[t]+=p+15)}return this},o.lib.init.prototype=o.lib,o})); diff --git a/third_party/pub_patches/fluttertoast/example/README.md b/third_party/pub_patches/fluttertoast/example/README.md new file mode 100644 index 000000000..cd375a691 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/README.md @@ -0,0 +1,16 @@ +# FlutterToast_example + +Demonstrates how to use the FlutterToast plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/third_party/pub_patches/fluttertoast/example/analysis_options.yaml b/third_party/pub_patches/fluttertoast/example/analysis_options.yaml new file mode 100644 index 000000000..61b6c4de1 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/third_party/pub_patches/fluttertoast/example/android/app/build.gradle b/third_party/pub_patches/fluttertoast/example/android/app/build.gradle new file mode 100644 index 000000000..ef7cb5a49 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/build.gradle @@ -0,0 +1,71 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 33 + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.example" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/debug/AndroidManifest.xml b/third_party/pub_patches/fluttertoast/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..45d523a2a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/AndroidManifest.xml b/third_party/pub_patches/fluttertoast/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..3f41384db --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/third_party/pub_patches/fluttertoast/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 000000000..e793a000d --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/drawable-v21/launch_background.xml b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/drawable/launch_background.xml b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..db77bb4b7 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..17987b79b Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09d439148 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5f1c8d34 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4d6372eeb Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/values-night/styles.xml b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..06952be74 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/values/styles.xml b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..cb1ef8805 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/android/app/src/profile/AndroidManifest.xml b/third_party/pub_patches/fluttertoast/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..45d523a2a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/third_party/pub_patches/fluttertoast/example/android/build.gradle b/third_party/pub_patches/fluttertoast/example/android/build.gradle new file mode 100644 index 000000000..ffb6e0ec7 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.7.0' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.4.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/third_party/pub_patches/fluttertoast/example/android/gradle.properties b/third_party/pub_patches/fluttertoast/example/android/gradle.properties new file mode 100644 index 000000000..94adc3a3f --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/third_party/pub_patches/fluttertoast/example/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/fluttertoast/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..c08cdc9e9 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip diff --git a/third_party/pub_patches/fluttertoast/example/android/gradlew b/third_party/pub_patches/fluttertoast/example/android/gradlew new file mode 100755 index 000000000..9d82f7891 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/third_party/pub_patches/fluttertoast/example/android/gradlew.bat b/third_party/pub_patches/fluttertoast/example/android/gradlew.bat new file mode 100644 index 000000000..8a0b282aa --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/third_party/pub_patches/fluttertoast/example/android/settings.gradle b/third_party/pub_patches/fluttertoast/example/android/settings.gradle new file mode 100644 index 000000000..44e62bcf0 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/third_party/pub_patches/fluttertoast/example/ios/Flutter/AppFrameworkInfo.plist b/third_party/pub_patches/fluttertoast/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..7c5696400 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Flutter/Debug.xcconfig b/third_party/pub_patches/fluttertoast/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..ec97fc6f3 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/fluttertoast/example/ios/Flutter/Release.xcconfig b/third_party/pub_patches/fluttertoast/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..c4855bfe2 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/fluttertoast/example/ios/Podfile b/third_party/pub_patches/fluttertoast/example/ios/Podfile new file mode 100644 index 000000000..f09c53e06 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.build_configurations.each do |config| + config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" + end + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/third_party/pub_patches/fluttertoast/example/ios/Podfile.lock b/third_party/pub_patches/fluttertoast/example/ios/Podfile.lock new file mode 100644 index 000000000..1be0743f5 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - Flutter (1.0.0) + - fluttertoast (0.0.2): + - Flutter + - Toast + - Toast (4.0.0) + +DEPENDENCIES: + - Flutter (from `Flutter`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + +SPEC REPOS: + trunk: + - Toast + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" + +SPEC CHECKSUMS: + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c + Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + +PODFILE CHECKSUM: 196b22cfac078643b05547cc40c0d80279b4874b + +COCOAPODS: 1.13.0 diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.pbxproj b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..14fb60f91 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,555 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + B258CC96A73DFA5D644773DE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C3E157E544CED11802E00C7 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7E6448B676433AEABB5439B3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 8831E6A950CD469DC16E09C6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 89F6F8D60DC6CEC891FB4473 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9C3E157E544CED11802E00C7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B258CC96A73DFA5D644773DE /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 373601E36306F84B036EB455 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9C3E157E544CED11802E00C7 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + C68FA61D2A053F5122846726 /* Pods */, + 373601E36306F84B036EB455 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + C68FA61D2A053F5122846726 /* Pods */ = { + isa = PBXGroup; + children = ( + 7E6448B676433AEABB5439B3 /* Pods-Runner.debug.xcconfig */, + 8831E6A950CD469DC16E09C6 /* Pods-Runner.release.xcconfig */, + 89F6F8D60DC6CEC891FB4473 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 069DA48D6E9C750356F2FF02 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 49226DDD737324CB669C67D4 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 069DA48D6E9C750356F2FF02 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 49226DDD737324CB669C67D4 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 82W3J47LPH; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 82W3J47LPH; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 82W3J47LPH; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..5e31d3d34 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/AppDelegate.swift b/third_party/pub_patches/fluttertoast/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..70693e4a8 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 000000000..dc9ada472 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 000000000..28c6bf030 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 000000000..f091b6b0b Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 000000000..4cde12118 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 000000000..d0ef06e7e Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 000000000..dcdc2306c Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 000000000..c8f9ed8f5 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 000000000..75b2d164a Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 000000000..c4df70d39 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 000000000..6a84f41e1 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 000000000..d0e1f5853 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000..0bedcf2fd --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/third_party/pub_patches/fluttertoast/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Base.lproj/Main.storyboard b/third_party/pub_patches/fluttertoast/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Info.plist b/third_party/pub_patches/fluttertoast/example/ios/Runner/Info.plist new file mode 100644 index 000000000..7f553465b --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/third_party/pub_patches/fluttertoast/example/ios/Runner/Runner-Bridging-Header.h b/third_party/pub_patches/fluttertoast/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..308a2a560 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/third_party/pub_patches/fluttertoast/example/lib/main.dart b/third_party/pub_patches/fluttertoast/example/lib/main.dart new file mode 100644 index 000000000..f4f99cb12 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/lib/main.dart @@ -0,0 +1,56 @@ +import 'package:fluttertoast_example/toast_context.dart'; +import 'package:fluttertoast_example/toast_no_context.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:flutter/material.dart'; + +GlobalKey navigatorKey = GlobalKey(); + +void main() => runApp( + MaterialApp( + builder: FToastBuilder(), + home: MyApp(), + navigatorKey: navigatorKey, + ), + ); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Toast"), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => ToastNoContext(), + )); + }, + child: Text("Flutter Toast No Context"), + ), + SizedBox( + height: 24.0, + ), + ElevatedButton( + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => ToastContext(), + )); + }, + child: Text("Flutter Toast Context"), + ), + ], + ), + ), + ); + } +} diff --git a/third_party/pub_patches/fluttertoast/example/lib/toast_context.dart b/third_party/pub_patches/fluttertoast/example/lib/toast_context.dart new file mode 100644 index 000000000..7b78623ce --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/lib/toast_context.dart @@ -0,0 +1,199 @@ +import 'package:fluttertoast_example/main.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class ToastContext extends StatefulWidget { + @override + _ToastContextState createState() => _ToastContextState(); +} + +class _ToastContextState extends State { + late FToast fToast; + + Widget toast = Container( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25.0), + color: Colors.greenAccent, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.check), + SizedBox( + width: 12.0, + ), + Text("This is a Custom Toast"), + ], + ), + ); + + _showToast() { + fToast.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + ); + } + + _showBuilderToast() { + fToast.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + positionedToastBuilder: (context, child) { + return Positioned( + child: child, + top: 16.0, + left: 16.0, + ); + }); + } + + _showToastCancel() { + Widget toastWithButton = Container( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25.0), + color: Colors.redAccent, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Text( + "This is a Custom Toast This is a Custom Toast This is a Custom Toast This is a Custom Toast This is a Custom Toast This is a Custom Toast", + softWrap: true, + style: TextStyle( + color: Colors.white, + ), + ), + ), + IconButton( + icon: Icon( + Icons.close, + ), + color: Colors.white, + onPressed: () { + fToast.removeCustomToast(); + }, + ) + ], + ), + ); + fToast.showToast( + child: toastWithButton, + gravity: ToastGravity.CENTER, + toastDuration: Duration(seconds: 50), + ); + } + + _queueToasts() { + fToast.showToast( + child: toast, + gravity: ToastGravity.CENTER, + toastDuration: Duration(seconds: 2), + ); + fToast.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + ); + fToast.showToast( + child: toast, + gravity: ToastGravity.TOP, + toastDuration: Duration(seconds: 2), + ); + fToast.showToast( + child: toast, + gravity: ToastGravity.CENTER, + toastDuration: Duration(seconds: 2), + ); + fToast.showToast( + child: toast, + gravity: ToastGravity.TOP, + toastDuration: Duration(seconds: 2), + ); + } + + _removeToast() { + fToast.removeCustomToast(); + } + + _removeAllQueuedToasts() { + fToast.removeQueuedCustomToasts(); + } + + @override + void initState() { + super.initState(); + fToast = FToast(); + fToast.init(navigatorKey.currentContext!); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Custom Toasts"), + ), + body: Center( + child: Column( + children: [ + SizedBox( + height: 24.0, + ), + ElevatedButton( + child: Text("Show Custom Toast"), + onPressed: () { + _showToast(); + }, + ), + ElevatedButton( + child: Text("Show Custom Toast via PositionedToastBuilder"), + onPressed: () { + _showBuilderToast(); + }, + ), + SizedBox( + height: 24.0, + ), + ElevatedButton( + child: Text("Custom Toast With Close Button"), + onPressed: () { + _showToastCancel(); + }, + ), + SizedBox( + height: 24.0, + ), + ElevatedButton( + child: Text("Queue Toasts"), + onPressed: () { + _queueToasts(); + }, + ), + SizedBox( + height: 24.0, + ), + ElevatedButton( + child: Text("Cancel Toast"), + onPressed: () { + _removeToast(); + }, + ), + SizedBox( + height: 24.0, + ), + ElevatedButton( + child: Text("Remove Queued Toasts"), + onPressed: () { + _removeAllQueuedToasts(); + }, + ), + ], + ), + ), + ); + } +} diff --git a/third_party/pub_patches/fluttertoast/example/lib/toast_no_context.dart b/third_party/pub_patches/fluttertoast/example/lib/toast_no_context.dart new file mode 100644 index 000000000..1c368fd97 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/lib/toast_no_context.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class ToastNoContext extends StatefulWidget { + @override + _ToastNoContextState createState() => _ToastNoContextState(); +} + +class _ToastNoContextState extends State { + void showLongToast() { + Fluttertoast.showToast( + msg: "This is Long Toast", + toastLength: Toast.LENGTH_LONG, + fontSize: 18.0, + ); + } + + void showWebColoredToast() { + Fluttertoast.showToast( + msg: "This is Colored Toast with android duration of 5 Sec", + toastLength: Toast.LENGTH_SHORT, + webBgColor: "#e74c3c", + textColor: Colors.black, + timeInSecForIosWeb: 5, + ); + } + + void showColoredToast() { + Fluttertoast.showToast( + msg: "This is Colored Toast with android of short", + toastLength: Toast.LENGTH_SHORT, + backgroundColor: Colors.red, + textColor: Colors.white); + } + + void showShortToast() { + Fluttertoast.showToast( + msg: "This is Short Toast", + toastLength: Toast.LENGTH_SHORT, + timeInSecForIosWeb: 1); + } + + void showTopShortToast() { + Fluttertoast.showToast( + msg: "This is Top Short Toast", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.TOP, + timeInSecForIosWeb: 1); + } + + void showCenterShortToast() { + Fluttertoast.showToast( + msg: "This is Center Short Toast", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 1); + } + + void cancelToast() { + Fluttertoast.cancel(); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return new MaterialApp( + home: new Scaffold( + appBar: new AppBar( + title: new Text('Flutter Toast'), + ), + body: new Center( + child: new Column( + children: [ + new Padding( + padding: const EdgeInsets.all(10.0), + child: new ElevatedButton( + child: new Text('Show Long Toast'), + onPressed: showLongToast), + ), + new Padding( + padding: const EdgeInsets.all(10.0), + child: new ElevatedButton( + child: new Text('Show Short Toast'), + onPressed: showShortToast), + ), + new Padding( + padding: const EdgeInsets.all(10.0), + child: new ElevatedButton( + child: new Text('Show Center Short Toast'), + onPressed: showCenterShortToast), + ), + new Padding( + padding: const EdgeInsets.all(10.0), + child: new ElevatedButton( + child: new Text('Show Top Short Toast'), + onPressed: showTopShortToast), + ), + new Padding( + padding: const EdgeInsets.all(10.0), + child: new ElevatedButton( + child: new Text('Show Colored Toast'), + onPressed: showColoredToast), + ), + new Padding( + padding: const EdgeInsets.all(10.0), + child: new ElevatedButton( + child: new Text('Show Web Colored Toast'), + onPressed: showWebColoredToast), + ), + new Padding( + padding: const EdgeInsets.all(10.0), + child: new ElevatedButton( + child: new Text('Cancel Toasts'), + onPressed: cancelToast, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/third_party/pub_patches/fluttertoast/example/linux/CMakeLists.txt b/third_party/pub_patches/fluttertoast/example/linux/CMakeLists.txt new file mode 100644 index 000000000..74c66dd44 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/CMakeLists.txt @@ -0,0 +1,138 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/third_party/pub_patches/fluttertoast/example/linux/flutter/CMakeLists.txt b/third_party/pub_patches/fluttertoast/example/linux/flutter/CMakeLists.txt new file mode 100644 index 000000000..d5bd01648 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugin_registrant.cc b/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..e71a16d23 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugin_registrant.h b/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugins.cmake b/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..2e1de87a7 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/third_party/pub_patches/fluttertoast/example/linux/main.cc b/third_party/pub_patches/fluttertoast/example/linux/main.cc new file mode 100644 index 000000000..e7c5c5437 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/third_party/pub_patches/fluttertoast/example/linux/my_application.cc b/third_party/pub_patches/fluttertoast/example/linux/my_application.cc new file mode 100644 index 000000000..0ba8f4309 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/third_party/pub_patches/fluttertoast/example/linux/my_application.h b/third_party/pub_patches/fluttertoast/example/linux/my_application.h new file mode 100644 index 000000000..72271d5e4 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Flutter/Flutter-Debug.xcconfig b/third_party/pub_patches/fluttertoast/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 000000000..4b81f9b2d --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/third_party/pub_patches/fluttertoast/example/macos/Flutter/Flutter-Release.xcconfig b/third_party/pub_patches/fluttertoast/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 000000000..5caa9d157 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/third_party/pub_patches/fluttertoast/example/macos/Flutter/GeneratedPluginRegistrant.swift b/third_party/pub_patches/fluttertoast/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 000000000..cccf817a5 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,10 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { +} diff --git a/third_party/pub_patches/fluttertoast/example/macos/Podfile b/third_party/pub_patches/fluttertoast/example/macos/Podfile new file mode 100644 index 000000000..049abe295 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/project.pbxproj b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..d9333e470 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,573 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* example.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..fb7259e17 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..1d526a16e --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/AppDelegate.swift b/third_party/pub_patches/fluttertoast/example/macos/Runner/AppDelegate.swift new file mode 100644 index 000000000..d53ef6437 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..a2ec33f19 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 000000000..82b6f9d9a Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 000000000..13b35eba5 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 000000000..0a3f5fa40 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 000000000..bdb57226d Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 000000000..f083318e0 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 000000000..326c0e72c Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 000000000..2f1632cfd Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Base.lproj/MainMenu.xib b/third_party/pub_patches/fluttertoast/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 000000000..80e867a4e --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/AppInfo.xcconfig b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 000000000..8b42559e8 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Debug.xcconfig b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 000000000..36b0fd946 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Release.xcconfig b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 000000000..dff4f4956 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Warnings.xcconfig b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 000000000..42bcbf478 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/DebugProfile.entitlements b/third_party/pub_patches/fluttertoast/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 000000000..dddb8a30c --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Info.plist b/third_party/pub_patches/fluttertoast/example/macos/Runner/Info.plist new file mode 100644 index 000000000..4789daa6a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/MainFlutterWindow.swift b/third_party/pub_patches/fluttertoast/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 000000000..2722837ec --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/third_party/pub_patches/fluttertoast/example/macos/Runner/Release.entitlements b/third_party/pub_patches/fluttertoast/example/macos/Runner/Release.entitlements new file mode 100644 index 000000000..852fa1a47 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/third_party/pub_patches/fluttertoast/example/pubspec.yaml b/third_party/pub_patches/fluttertoast/example/pubspec.yaml new file mode 100644 index 000000000..14ac8e562 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/pubspec.yaml @@ -0,0 +1,71 @@ +name: fluttertoast_example +description: Demonstrates how to use the FlutterToast plugin. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: '>=2.12.0 <4.0.0' + +dependencies: + flutter: + sdk: flutter + + fluttertoast: + # When depending on this package from a real application you should use: + # FlutterToast: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/third_party/pub_patches/fluttertoast/example/test/widget_test.dart b/third_party/pub_patches/fluttertoast/example/test/widget_test.dart new file mode 100644 index 000000000..e3b992916 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:fluttertoast_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => widget is Text && + widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/third_party/pub_patches/fluttertoast/example/web/favicon.png b/third_party/pub_patches/fluttertoast/example/web/favicon.png new file mode 100644 index 000000000..8aaa46ac1 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/web/favicon.png differ diff --git a/third_party/pub_patches/fluttertoast/example/web/icons/Icon-192.png b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-192.png new file mode 100644 index 000000000..b749bfef0 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-192.png differ diff --git a/third_party/pub_patches/fluttertoast/example/web/icons/Icon-512.png b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-512.png new file mode 100644 index 000000000..88cfd48df Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-512.png differ diff --git a/third_party/pub_patches/fluttertoast/example/web/icons/Icon-maskable-192.png b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-maskable-192.png new file mode 100644 index 000000000..eb9b4d76e Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-maskable-192.png differ diff --git a/third_party/pub_patches/fluttertoast/example/web/icons/Icon-maskable-512.png b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-maskable-512.png new file mode 100644 index 000000000..d69c56691 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/web/icons/Icon-maskable-512.png differ diff --git a/third_party/pub_patches/fluttertoast/example/web/index.html b/third_party/pub_patches/fluttertoast/example/web/index.html new file mode 100644 index 000000000..41b3bc336 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/web/index.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + example + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/web/manifest.json b/third_party/pub_patches/fluttertoast/example/web/manifest.json new file mode 100644 index 000000000..096edf8fe --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/third_party/pub_patches/fluttertoast/example/windows/CMakeLists.txt b/third_party/pub_patches/fluttertoast/example/windows/CMakeLists.txt new file mode 100644 index 000000000..c0270746b --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/CMakeLists.txt @@ -0,0 +1,101 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(example LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/third_party/pub_patches/fluttertoast/example/windows/flutter/CMakeLists.txt b/third_party/pub_patches/fluttertoast/example/windows/flutter/CMakeLists.txt new file mode 100644 index 000000000..930d2071a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,104 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugin_registrant.cc b/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..8b6d4680a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugin_registrant.h b/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..dc139d85a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugins.cmake b/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000..b93c4c30c --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/CMakeLists.txt b/third_party/pub_patches/fluttertoast/example/windows/runner/CMakeLists.txt new file mode 100644 index 000000000..17411a8ab --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/Runner.rc b/third_party/pub_patches/fluttertoast/example/windows/runner/Runner.rc new file mode 100644 index 000000000..0f5c08571 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/flutter_window.cpp b/third_party/pub_patches/fluttertoast/example/windows/runner/flutter_window.cpp new file mode 100644 index 000000000..b43b9095e --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/flutter_window.h b/third_party/pub_patches/fluttertoast/example/windows/runner/flutter_window.h new file mode 100644 index 000000000..6da0652f0 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/main.cpp b/third_party/pub_patches/fluttertoast/example/windows/runner/main.cpp new file mode 100644 index 000000000..bcb57b0e2 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/resource.h b/third_party/pub_patches/fluttertoast/example/windows/runner/resource.h new file mode 100644 index 000000000..66a65d1e4 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/resources/app_icon.ico b/third_party/pub_patches/fluttertoast/example/windows/runner/resources/app_icon.ico new file mode 100644 index 000000000..c04e20caf Binary files /dev/null and b/third_party/pub_patches/fluttertoast/example/windows/runner/resources/app_icon.ico differ diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/runner.exe.manifest b/third_party/pub_patches/fluttertoast/example/windows/runner/runner.exe.manifest new file mode 100644 index 000000000..a42ea7687 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/utils.cpp b/third_party/pub_patches/fluttertoast/example/windows/runner/utils.cpp new file mode 100644 index 000000000..f5bf9fa0f --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/utils.h b/third_party/pub_patches/fluttertoast/example/windows/runner/utils.h new file mode 100644 index 000000000..3879d5475 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/win32_window.cpp b/third_party/pub_patches/fluttertoast/example/windows/runner/win32_window.cpp new file mode 100644 index 000000000..c10f08dc7 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/third_party/pub_patches/fluttertoast/example/windows/runner/win32_window.h b/third_party/pub_patches/fluttertoast/example/windows/runner/win32_window.h new file mode 100644 index 000000000..17ba43112 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/example/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/third_party/pub_patches/fluttertoast/ios/Classes/FluttertoastPlugin.h b/third_party/pub_patches/fluttertoast/ios/Classes/FluttertoastPlugin.h new file mode 100644 index 000000000..2a83d0f94 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/ios/Classes/FluttertoastPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FluttertoastPlugin : NSObject +@end diff --git a/third_party/pub_patches/fluttertoast/ios/Classes/FluttertoastPlugin.m b/third_party/pub_patches/fluttertoast/ios/Classes/FluttertoastPlugin.m new file mode 100644 index 000000000..60ccf341a --- /dev/null +++ b/third_party/pub_patches/fluttertoast/ios/Classes/FluttertoastPlugin.m @@ -0,0 +1,142 @@ +#import "FluttertoastPlugin.h" +#import + +static NSString *const CHANNEL_NAME = @"PonnamKarthik/fluttertoast"; + +@interface FluttertoastPlugin () +@property(nonatomic, retain) FlutterMethodChannel *channel; +@property(nonatomic, assign) BOOL isKeyboardVisible; +@end + +@implementation FluttertoastPlugin { + FlutterResult _result; + +} + ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:CHANNEL_NAME + binaryMessenger:[registrar messenger]]; + FluttertoastPlugin *instance = [[FluttertoastPlugin alloc] init]; + instance.channel = channel; + [registrar addMethodCallDelegate:instance channel:channel]; + +} + +- (instancetype)init { + self = [super init]; + if (self) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; +} + + +- (void)keyboardWillShow { + self.isKeyboardVisible = YES; +} + +- (void)keyboardWillHide { + self.isKeyboardVisible = NO; +} + +- (UIColor*) colorWithHex: (NSUInteger)hex { + CGFloat red, green, blue, alpha; + + red = ((CGFloat)((hex >> 16) & 0xFF)) / ((CGFloat)0xFF); + green = ((CGFloat)((hex >> 8) & 0xFF)) / ((CGFloat)0xFF); + blue = ((CGFloat)((hex >> 0) & 0xFF)) / ((CGFloat)0xFF); + alpha = hex > 0xFFFFFF ? ((CGFloat)((hex >> 24) & 0xFF)) / ((CGFloat)0xFF) : 1; + + return [UIColor colorWithRed: red green:green blue:blue alpha:alpha]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + if([@"cancel" isEqualToString:call.method]) { + __weak typeof(self) weakSelf = self; + [[weakSelf _readKeyWindow] hideAllToasts]; + result([NSNumber numberWithBool:true]); + } else if ([@"showToast" isEqualToString:call.method]) { + NSString *msg = call.arguments[@"msg"]; + NSString *gravity = call.arguments[@"gravity"]; + NSString *durationTime = call.arguments[@"time"]; + NSNumber *bgcolor = call.arguments[@"bgcolor"]; + NSNumber *textcolor = call.arguments[@"textcolor"]; +// NSNumber *size = call.arguments[@"size"]; + NSNumber *fontSize = call.arguments[@"fontSize"]; + + if ([fontSize isKindOfClass:[NSNull class]]) { + fontSize = [[NSNumber alloc] initWithInt:16]; + } + + CGFloat cgf = [fontSize doubleValue]; + int time = 1; + @try { + time = [durationTime intValue]; + } @catch (NSException *e) { + time = 3; + } + + if (time > 10) time = 10; + else if (time < 1) time = 1; + + + CSToastStyle *style = [[CSToastStyle alloc] initWithDefaultStyle]; + style.messageFont = [UIFont systemFontOfSize:cgf]; + style.backgroundColor = [self colorWithHex:bgcolor.unsignedIntegerValue]; + style.messageColor = [self colorWithHex:textcolor.unsignedIntegerValue]; + +// if (@available(iOS 11.0, *)) { +// UIWindow *window = UIApplication.sharedApplication.keyWindow; +// } + + if ([gravity isEqualToString:@"top"]) { + + [self makeToast:msg duration:time position:CSToastPositionTop style:style]; + + } else if ([gravity isEqualToString:@"center"]) { + + [self makeToast:msg duration:time position:CSToastPositionCenter style:style]; + + } else { + + [self makeToast:msg duration:time position:CSToastPositionBottom style:style]; + + } + result([NSNumber numberWithBool:true]); + + } else { + result(FlutterMethodNotImplemented); + } +} + +- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position style:(CSToastStyle *)style { + __weak typeof(self) weakSelf = self; + // Fixed if the keyboard disappear, the toast disappear at once, because the window where the keyboard is is gone. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [[weakSelf _readKeyWindow] makeToast:message duration:duration position:position style:style]; + }); +} + +#pragma mark - read the key window + +- (UIWindow *)_readKeyWindow { + NSArray *windows = UIApplication.sharedApplication.windows; + if (self.isKeyboardVisible) { + return windows.lastObject; + } + for (UIWindow *window in windows) { + if (window.isKeyWindow) { + return window; + } + } + return nil; +} + +@end diff --git a/third_party/pub_patches/fluttertoast/ios/Resources/PrivacyInfo.xcprivacy b/third_party/pub_patches/fluttertoast/ios/Resources/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..a34b7e2e6 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/ios/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/third_party/pub_patches/fluttertoast/ios/fluttertoast.podspec b/third_party/pub_patches/fluttertoast/ios/fluttertoast.podspec new file mode 100644 index 000000000..4cc8876ea --- /dev/null +++ b/third_party/pub_patches/fluttertoast/ios/fluttertoast.podspec @@ -0,0 +1,21 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'fluttertoast' + s.version = '0.0.2' + s.summary = 'Toast Library for Flutter' + s.description = <<-DESC +Toast Library for FLutter + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Karthik Ponnam' => 'ponnamkarthik3@gmail.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.dependency 'Toast' + s.pod_target_xcconfig = {'DEFINES_MODULE' => 'YES'} + s.resource_bundles = {'fluttertoast_privacy' => ['Resources/PrivacyInfo.xcprivacy']} +end diff --git a/third_party/pub_patches/fluttertoast/lib/fluttertoast.dart b/third_party/pub_patches/fluttertoast/lib/fluttertoast.dart new file mode 100644 index 000000000..27d5b08c1 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/lib/fluttertoast.dart @@ -0,0 +1,439 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +/// Toast Length +/// Only for Android Platform +enum Toast { + /// Show Short toast for 1 sec + LENGTH_SHORT, + + /// Show Long toast for 5 sec + LENGTH_LONG +} + +/// ToastGravity +/// Used to define the position of the Toast on the screen +enum ToastGravity { + TOP, + BOTTOM, + CENTER, + TOP_LEFT, + TOP_RIGHT, + BOTTOM_LEFT, + BOTTOM_RIGHT, + CENTER_LEFT, + CENTER_RIGHT, + SNACKBAR, + NONE +} + +/// Plugin to show a toast message on screen +/// Only for android, ios and Web platforms +class Fluttertoast { + /// [MethodChannel] used to communicate with the platform side. + static const MethodChannel _channel = + const MethodChannel('PonnamKarthik/fluttertoast'); + + /// Let say you have an active show + /// Use this method to hide the toast immediately + static Future cancel() async { + bool? res = await _channel.invokeMethod("cancel"); + return res; + } + + /// Show the [msg] via native platform's toast. + /// + /// On Android uses Toast. + /// On iOS uses https://github.com/scalessec/Toast plugin. + /// On web uses https://github.com/apvarun/toastify-js library. + /// + /// Parameter [msg] is required and all remaining are optional. + /// + /// The [fontAsset] is the path to your Flutter asset to use in toast. + /// If not specified platform's default font will be used. + static Future showToast({ + required String msg, + Toast? toastLength, + int timeInSecForIosWeb = 1, + double? fontSize, + String? fontAsset, + ToastGravity? gravity, + Color? backgroundColor, + Color? textColor, + bool webShowClose = false, + webBgColor = "linear-gradient(to right, #00b09b, #96c93d)", + webPosition = "right", + }) async { + String toast = "short"; + if (toastLength == Toast.LENGTH_LONG) { + toast = "long"; + } + + String gravityToast = "bottom"; + if (gravity == ToastGravity.TOP) { + gravityToast = "top"; + } else if (gravity == ToastGravity.CENTER) { + gravityToast = "center"; + } else { + gravityToast = "bottom"; + } + +//lines from 78 to 97 have been changed in order to solve issue #328 + if (backgroundColor == null) { + backgroundColor = Colors.black; + } + if (textColor == null) { + textColor = Colors.white; + } + final Map params = { + 'msg': msg, + 'length': toast, + 'time': timeInSecForIosWeb, + 'gravity': gravityToast, + 'bgcolor': backgroundColor.value, + 'iosBgcolor': backgroundColor.value, + 'textcolor': textColor.value, + 'iosTextcolor': textColor.value, + 'fontSize': fontSize, + 'fontAsset': fontAsset, + 'webShowClose': webShowClose, + 'webBgColor': webBgColor, + 'webPosition': webPosition + }; + + bool? res = await _channel.invokeMethod('showToast', params); + return res; + } +} + +/// Signature for a function to buildCustom Toast +typedef PositionedToastBuilder = Widget Function( + BuildContext context, Widget child); + +/// Runs on dart side this has no interaction with the Native Side +/// Works with all platforms just in two lines of code +/// final fToast = FToast().init(context) +/// fToast.showToast(child) +/// +class FToast { + BuildContext? context; + + static final FToast _instance = FToast._internal(); + + /// Prmary Constructor for FToast + factory FToast() { + return _instance; + } + + /// Take users Context and saves to avariable + FToast init(BuildContext context) { + _instance.context = context; + return _instance; + } + + FToast._internal(); + + OverlayEntry? _entry; + List<_ToastEntry> _overlayQueue = []; + Timer? _timer; + Timer? _fadeTimer; + + /// Internal function which handles the adding + /// the overlay to the screen + /// + _showOverlay() { + if (_overlayQueue.isEmpty) { + _entry = null; + return; + } + if (context == null) { + /// Need to clear queue + removeQueuedCustomToasts(); + throw ("Error: Context is null, Please call init(context) before showing toast."); + } + + /// To prevent exception "Looking up a deactivated widget's ancestor is unsafe." + /// which can be thrown if context was unmounted (e.g. screen with given context was popped) + /// TODO: revert this change when envoirment will be Flutter >= 3.7.0 + // if (context?.mounted != true) { + // if (kDebugMode) { + // print( + // 'FToast: Context was unmuted, can not show ${_overlayQueue.length} toast.'); + // } + + // /// Need to clear queue + // removeQueuedCustomToasts(); + // return; // Or maybe thrown error too + // } + OverlayState? _overlay; + try { + _overlay = Overlay.of(context!); + } catch (err) { + removeQueuedCustomToasts(); + throw ("""Error: Overlay is null. + Please don't use top of the widget tree context (such as Navigator or MaterialApp) or + create overlay manually in MaterialApp builder. + More information + - https://github.com/ponnamkarthik/FlutterToast/issues/393 + - https://github.com/ponnamkarthik/FlutterToast/issues/234"""); + } + + /// Create entry only after all checks + _ToastEntry _toastEntry = _overlayQueue.removeAt(0); + _entry = _toastEntry.entry; + _overlay.insert(_entry!); + + _timer = Timer(_toastEntry.duration, () { + _fadeTimer = Timer(_toastEntry.fadeDuration, () { + removeCustomToast(); + }); + }); + } + + /// If any active toast present + /// call removeCustomToast to hide the toast immediately + removeCustomToast() { + _timer?.cancel(); + _fadeTimer?.cancel(); + _timer = null; + _fadeTimer = null; + _entry?.remove(); + _entry = null; + _showOverlay(); + } + + /// FToast maintains a queue for every toast + /// if we called showToast for 3 times we all to queue + /// and show them one after another + /// + /// call removeCustomToast to hide the toast immediately + removeQueuedCustomToasts() { + _timer?.cancel(); + _fadeTimer?.cancel(); + _timer = null; + _fadeTimer = null; + _overlayQueue.clear(); + _entry?.remove(); + _entry = null; + } + + /// showToast accepts all the required paramenters and prepares the child + /// calls _showOverlay to display toast + /// + /// Paramenter [child] is requried + /// toastDuration default is 2 seconds + /// fadeDuration default is 350 milliseconds + void showToast({ + required Widget child, + PositionedToastBuilder? positionedToastBuilder, + Duration toastDuration = const Duration(seconds: 2), + ToastGravity? gravity, + Duration fadeDuration = const Duration(milliseconds: 350), + bool ignorePointer = false, + bool isDismissable = false, + }) { + if (context == null) + throw ("Error: Context is null, Please call init(context) before showing toast."); + Widget newChild = _ToastStateFul( + child, + toastDuration, + fadeDuration, + ignorePointer, + !isDismissable + ? null + : () { + removeCustomToast(); + }); + + /// Check for keyboard open + /// If open will ignore the gravity bottom and change it to center + if (gravity == ToastGravity.BOTTOM) { + if (MediaQuery.of(context!).viewInsets.bottom != 0) { + gravity = ToastGravity.CENTER; + } + } + + OverlayEntry newEntry = OverlayEntry(builder: (context) { + if (positionedToastBuilder != null) + return positionedToastBuilder(context, newChild); + return _getPostionWidgetBasedOnGravity(newChild, gravity); + }); + _overlayQueue.add(_ToastEntry( + entry: newEntry, duration: toastDuration, fadeDuration: fadeDuration)); + if (_timer == null) _showOverlay(); + } + + /// _getPostionWidgetBasedOnGravity generates [Positioned] [Widget] + /// based on the gravity [ToastGravity] provided by the user in + /// [showToast] + _getPostionWidgetBasedOnGravity(Widget child, ToastGravity? gravity) { + switch (gravity) { + case ToastGravity.TOP: + return Positioned(top: 100.0, left: 24.0, right: 24.0, child: child); + case ToastGravity.TOP_LEFT: + return Positioned(top: 100.0, left: 24.0, child: child); + case ToastGravity.TOP_RIGHT: + return Positioned(top: 100.0, right: 24.0, child: child); + case ToastGravity.CENTER: + return Positioned( + top: 50.0, bottom: 50.0, left: 24.0, right: 24.0, child: child); + case ToastGravity.CENTER_LEFT: + return Positioned(top: 50.0, bottom: 50.0, left: 24.0, child: child); + case ToastGravity.CENTER_RIGHT: + return Positioned(top: 50.0, bottom: 50.0, right: 24.0, child: child); + case ToastGravity.BOTTOM_LEFT: + return Positioned(bottom: 50.0, left: 24.0, child: child); + case ToastGravity.BOTTOM_RIGHT: + return Positioned(bottom: 50.0, right: 24.0, child: child); + case ToastGravity.SNACKBAR: + return Positioned( + bottom: MediaQuery.of(context!).viewInsets.bottom, + left: 0, + right: 0, + child: child); + case ToastGravity.NONE: + return Positioned.fill(child: child); + case ToastGravity.BOTTOM: + default: + return Positioned(bottom: 50.0, left: 24.0, right: 24.0, child: child); + } + } +} + +/// Simple builder method to create a [TransitionBuilder] +/// and for the use in MaterialApp builder method +// ignore: non_constant_identifier_names +TransitionBuilder FToastBuilder() { + return (context, child) { + return _FToastHolder( + child: child!, + ); + }; +} + +/// Simple StatelessWidget which holds the child +/// and creates an [Overlay] to display the toast +class _FToastHolder extends StatelessWidget { + const _FToastHolder({Key? key, required this.child}) : super(key: key); + + final Widget child; + + @override + Widget build(BuildContext context) { + return Overlay( + initialEntries: [ + OverlayEntry( + builder: (BuildContext ctx) { + return child; + }, + ), + ], + ); + } +} + +/// internal class [_ToastEntry] which maintains +/// each [OverlayEntry] and [Duration] for every toast user +/// triggered +class _ToastEntry { + final OverlayEntry entry; + final Duration duration; + final Duration fadeDuration; + + _ToastEntry({ + required this.entry, + required this.duration, + required this.fadeDuration, + }); +} + +/// internal [StatefulWidget] which handles the show and hide +/// animations for [FToast] +class _ToastStateFul extends StatefulWidget { + _ToastStateFul(this.child, this.duration, this.fadeDuration, + this.ignorePointer, this.onDismiss, + {Key? key}) + : super(key: key); + + final Widget child; + final Duration duration; + final Duration fadeDuration; + final bool ignorePointer; + final VoidCallback? onDismiss; + + @override + ToastStateFulState createState() => ToastStateFulState(); +} + +/// State for [_ToastStateFul] +class ToastStateFulState extends State<_ToastStateFul> + with SingleTickerProviderStateMixin { + /// Start the showing animations for the toast + showIt() { + _animationController!.forward(); + } + + /// Start the hidding animations for the toast + hideIt() { + _animationController!.reverse(); + _timer?.cancel(); + } + + /// Controller to start and hide the animation + AnimationController? _animationController; + late Animation _fadeAnimation; + + Timer? _timer; + + @override + void initState() { + _animationController = AnimationController( + vsync: this, + duration: widget.fadeDuration, + ); + _fadeAnimation = + CurvedAnimation(parent: _animationController!, curve: Curves.easeIn); + super.initState(); + + showIt(); + _timer = Timer(widget.duration, () { + hideIt(); + }); + } + + @override + void deactivate() { + _timer?.cancel(); + _animationController!.stop(); + super.deactivate(); + } + + @override + void dispose() { + _timer?.cancel(); + _animationController?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: widget.onDismiss == null ? null : () => widget.onDismiss!(), + behavior: HitTestBehavior.translucent, + child: IgnorePointer( + ignoring: widget.ignorePointer, + child: FadeTransition( + opacity: _fadeAnimation as Animation, + child: Center( + child: Material( + color: Colors.transparent, + child: widget.child, + ), + ), + ), + ), + ); + } +} diff --git a/third_party/pub_patches/fluttertoast/lib/fluttertoast_web.dart b/third_party/pub_patches/fluttertoast/lib/fluttertoast_web.dart new file mode 100644 index 000000000..ad3ed39f1 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/lib/fluttertoast_web.dart @@ -0,0 +1,142 @@ +import 'dart:async'; +import 'dart:js_interop'; +import 'package:web/web.dart' as web; +import 'dart:ui_web' as ui; +import 'package:flutter/services.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +/// Plugin Class to show a toast message on screen for web +class FluttertoastWebPlugin { + /// Constructor class + /// which calls the metohd to inject JS and CSS in to dom + FluttertoastWebPlugin() { + injectCssAndJSLibraries(); + } + + /// Registers [MethodChannel] used to communicate with the platform side. + static void registerWith(Registrar registrar) { + final MethodChannel channel = MethodChannel( + 'PonnamKarthik/fluttertoast', const StandardMethodCodec(), registrar); + final FluttertoastWebPlugin instance = FluttertoastWebPlugin(); + channel.setMethodCallHandler(instance.handleMethodCall); + } + + /// Handle Method Callbacks from [MethodChannel]. + Future handleMethodCall(MethodCall call) async { + switch (call.method) { + case 'showToast': + showToast(call.arguments); + return true; + default: + throw PlatformException( + code: 'Unimplemented', + details: "The fluttertoast plugin for web doesn't implement " + "the method '${call.method}'"); + } + } + + /// showToast which parses the required arguments and pass + /// it to [addHtmlToast] + showToast(args) { + String msg = args['msg']; + String? gravity = "top"; + if (args['gravity'] == "top" || args['gravity'] == "bottom") { + gravity = args["gravity"]; + } + + String position = args['webPosition'] ?? 'right'; + + String bgColor = + args['webBgColor'] ?? "linear-gradient(to right, #00b09b, #96c93d)"; + + int? textColor = args['textcolor']; + + int time = args['time'] == null + ? 3000 + : (int.parse(args['time'].toString()) * 1000); + + bool showClose = args['webShowClose'] ?? false; + + addHtmlToast( + msg: msg, + gravity: gravity, + position: position, + bgcolor: bgColor, + showClose: showClose, + time: time, + textColor: textColor); + } + + /// [injectCssAndJSLibraries] which add the JS and CSS files into DOM + Future injectCssAndJSLibraries() async { + final List> loading = >[]; + final List tags = []; + + final cssUrl = ui.assetManager.getAssetUrl( + 'packages/fluttertoast/assets/toastify.css', + ); + final web.HTMLLinkElement css = web.HTMLLinkElement() + ..id = 'toast-css' + ..setAttribute("rel", "stylesheet") + ..href = cssUrl; + tags.add(css); + + final jsUrl = ui.assetManager.getAssetUrl( + 'packages/fluttertoast/assets/toastify.js', + ); + final web.HTMLScriptElement script = web.HTMLScriptElement() + ..async = true + // ..defer = true + ..src = jsUrl; + loading.add(script.onLoad.first); + tags.add(script); + for (final web.HTMLElement tag in tags) { + web.document.querySelector('head')!.append(tag); + } + + await Future.wait(loading); + } + + /// injects Final [Toastify] code with all the parameters to + /// make toast visible on web + addHtmlToast( + {String msg = "", + String? gravity = "top", + String position = "right", + String bgcolor = "linear-gradient(to right, #00b09b, #96c93d)", + int time = 3000, + bool showClose = false, + int? textColor}) { + String m = msg.replaceAll("'", "\\'").replaceAll("\n", "
"); + web.Element? ele = web.document.querySelector("#toast-content"); + String content = """ + var toastElement = Toastify({ + text: '$m', + gravity: '$gravity', + position: '$position', + duration: $time, + close: $showClose, + backgroundColor: "$bgcolor", + }); + toastElement.showToast(); + """; + if (web.document.querySelector("#toast-content") != null) { + ele!.remove(); + } + final web.HTMLScriptElement scriptText = web.HTMLScriptElement() + ..id = "toast-content"; + if (scriptText.innerHTML is String) { + scriptText.innerHTML = content.toJS.toString() as dynamic; + } else { + scriptText.innerHTML = content.toJS as dynamic; + } + web.document.body!.append(scriptText); + if (textColor != null) { + web.Element toast = web.document.querySelector('.toastify')!; + String tcRadix = textColor.toRadixString(16); + final String tC = "${tcRadix.substring(2)}${tcRadix.substring(0, 2)}"; + final style = toast.getAttribute('style') ?? ''; + toast.setAttribute('style', '$style color: #$tC;'); + } + } +} diff --git a/third_party/pub_patches/fluttertoast/pubspec.yaml b/third_party/pub_patches/fluttertoast/pubspec.yaml new file mode 100644 index 000000000..c7bd9eb01 --- /dev/null +++ b/third_party/pub_patches/fluttertoast/pubspec.yaml @@ -0,0 +1,30 @@ +name: fluttertoast +description: Toast Library for Flutter, Easily create toast messages in single line of code +version: 8.2.8 +homepage: https://github.com/PonnamKarthik/FlutterToast +issue_tracker: https://github.com/ponnamkarthik/FlutterToast/issues + +environment: + sdk: '>=2.12.0 <4.0.0' + flutter: ">=1.10.0" + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + web: ">=0.5.1 <2.0.0" + +flutter: + plugin: + platforms: + android: + package: io.github.ponnamkarthik.toast.fluttertoast + pluginClass: FlutterToastPlugin + ios: + pluginClass: FluttertoastPlugin + web: + pluginClass: FluttertoastWebPlugin + fileName: fluttertoast_web.dart + assets: + - assets/ diff --git a/third_party/pub_patches/fluttertoast/screenshot/1.png b/third_party/pub_patches/fluttertoast/screenshot/1.png new file mode 100644 index 000000000..63ad60f4b Binary files /dev/null and b/third_party/pub_patches/fluttertoast/screenshot/1.png differ diff --git a/third_party/pub_patches/fluttertoast/screenshot/11.jpg b/third_party/pub_patches/fluttertoast/screenshot/11.jpg new file mode 100644 index 000000000..82a4d1e46 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/screenshot/11.jpg differ diff --git a/third_party/pub_patches/fluttertoast/screenshot/2.png b/third_party/pub_patches/fluttertoast/screenshot/2.png new file mode 100644 index 000000000..e10544620 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/screenshot/2.png differ diff --git a/third_party/pub_patches/fluttertoast/screenshot/3.png b/third_party/pub_patches/fluttertoast/screenshot/3.png new file mode 100644 index 000000000..a365f2c70 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/screenshot/3.png differ diff --git a/third_party/pub_patches/fluttertoast/screenshot/4.png b/third_party/pub_patches/fluttertoast/screenshot/4.png new file mode 100644 index 000000000..060405cd9 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/screenshot/4.png differ diff --git a/third_party/pub_patches/fluttertoast/screenshot/toast_deprecated_setview.png b/third_party/pub_patches/fluttertoast/screenshot/toast_deprecated_setview.png new file mode 100644 index 000000000..e549e3f93 Binary files /dev/null and b/third_party/pub_patches/fluttertoast/screenshot/toast_deprecated_setview.png differ diff --git a/third_party/pub_patches/sensors_plus/CHANGELOG.md b/third_party/pub_patches/sensors_plus/CHANGELOG.md new file mode 100644 index 000000000..2fa4012b8 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/CHANGELOG.md @@ -0,0 +1,217 @@ +## 1.4.1 + + - **CHORE**: Version tagging using melos. + +## 1.4.0 + +- iOS: Corrects magnetometer implementation, returning calibrated values from + `DeviceMotion` sensor rather than raw sensor samples + +## 1.3.4+1 + +- Add issue_tracker link. + +## 1.3.4 + +- Additonal fixes for crash issue: "Error: Sending a message before the FlutterEngine has been run." + +## 1.3.3 + +- Fix: "crash on iOS: Sending a message before the FlutterEngine has been run" + +## 1.3.2 + +- Fix: Android no longer crashes when app is closed if streams weren't listened to +- Update flutter_lints to 2.0.1 +- Fix analyzer warnings + +## 1.3.1 + +- Fix: unregister listeners on Android in `onDetachFromEngine` to not receive sensors events after app was killed + +## 1.3.0 + +- Android: Migrate to Kotlin +- Android: Update dependencies, build config updates + +## 1.2.2 + +- Fix example embedding issues + +## 1.2.1 + +- Upgrade Android compile SDK version +- Several code improvements + +## 1.2.0 + +- migrate integration_test to flutter sdk + +## 1.1.0 + +- Adds magnetometer support + +## 1.0.2 + +- Android: migrate to mavenCentral + +## 1.0.1 + +- Improve documentation + +## 1.0.0 + +- Migrated to null-safety + +## 0.6.0 + +- Renamed Method Channel + +## 0.5.0 + +- Transfer to plus-plugins monorepo + +## 0.4.2+5 + +- Transfer package to Flutter Community under new name `sensors_plus`. + +## 0.4.2+4 + +- Update package:e2e -> package:integration_test + +## 0.4.2+3 + +- Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.2+2 + +- Post-v2 Android embedding cleanup. + +## 0.4.2+1 + +- Update lower bound of dart dependency to 2.1.0. + +## 0.4.2 + +- Remove Android dependencies fallback. +- Require Flutter SDK 1.12.13+hotfix.5 or greater. +- Fix CocoaPods podspec lint warnings. + +## 0.4.1+10 + +- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). + +## 0.4.1+9 + +- Replace deprecated `getFlutterEngine` call on Android. + +## 0.4.1+8 + +- Make the pedantic dev_dependency explicit. + +## 0.4.1+7 + +- Fixed example userAccelerometerEvent in documentation + +## 0.4.1+6 + +- Migrate from deprecated BinaryMessages to ServicesBinding.instance.defaultBinaryMessenger. +- Require Flutter SDK 1.12.13+hotfix.5 or greater (current stable). + +## 0.4.1+5 + +- Fix example `setState()` called after `dispose()` by canceling the timer. + +## 0.4.1+4 + +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. + +## 0.4.1+3 + +- Improve documentation and add unit test coverage. + +## 0.4.1+2 + +- Remove AndroidX warnings. + +## 0.4.1+1 + +- Include lifecycle dependency as a compileOnly one on Android to resolve + potential version conflicts with other transitive libraries. + +## 0.4.1 + +- Support the v2 Android embedder. +- Update to AndroidX. +- Migrate to using the new e2e test binding. +- Add a e2e test. + +## 0.4.0+3 + +- Update and migrate iOS example project. +- Define clang module for iOS. + +## 0.4.0+2 + +- Suppress deprecation warning for BinaryMessages. See: https://github.com/flutter/flutter/issues/33446 + +## 0.4.0+1 + +- Log a more detailed warning at build time about the previous AndroidX + migration. + +## 0.4.0 + +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## 0.3.5 + +- Added missing test package dependency. + +## 0.3.4 + +- Make sensors Dart 2 compliant. + +## 0.3.3 + +- Updated Gradle tooling to match Android Studio 3.1.2. + +## 0.3.2 + +- Added user acceleration sensor events (i.e. accelerometer without gravity). + +## 0.3.1 + +- Fixed Dart 2 type error with iOS sensor events. + +## 0.3.0 + +- **Breaking change**. Set SDK constraints to match the Flutter beta release. + +## 0.2.1 + +- Fixed warnings from the Dart 2.0 analyzer. +- Simplified and upgraded Android project template to Android SDK 27. +- Updated package description. + +## 0.2.0 + +- **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin + 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in + order to use this version of the plugin. Instructions can be found + [here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1). + +## 0.1.1 + +- Added FLT prefix to iOS types. + +## 0.1.0 + +- Initial Open Source release. diff --git a/third_party/pub_patches/sensors_plus/LICENSE b/third_party/pub_patches/sensors_plus/LICENSE new file mode 100644 index 000000000..c89293372 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/pub_patches/sensors_plus/README.md b/third_party/pub_patches/sensors_plus/README.md new file mode 100644 index 000000000..d5fba8920 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/README.md @@ -0,0 +1,72 @@ +# Sensors Plus + +[![Flutter Community: sensors_plus](https://fluttercommunity.dev/_github/header/sensors_plus)](https://github.com/fluttercommunity/community) + +[![sensors_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/sensors_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/sensors_plus.yaml) +[![pub points](https://img.shields.io/pub/points/sensors_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/sensors_plus/score) +[![pub package](https://img.shields.io/pub/v/battery_plus.svg)](https://pub.dev/packages/battery_plus) + +build + +A Flutter plugin to access the accelerometer, gyroscope, and magnetometer +sensors. + +## Platform Support + +| Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :---: | :---: | :---: | :---: | :-----: | +| ✔️ | ✔️ | | ✔️ | | | + +## Usage + +To use this plugin, add `sensors_plus` as a [dependency in your pubspec.yaml +file](https://plus.fluttercommunity.dev/docs/overview). + +This will expose four classes of sensor events through four different +streams. + +- `AccelerometerEvent`s describe the velocity of the device, including the + effects of gravity. Put simply, you can use accelerometer readings to tell if + the device is moving in a particular direction. +- `UserAccelerometerEvent`s also describe the velocity of the device, but don't + include gravity. They can also be thought of as just the user's affect on the + device. +- `GyroscopeEvent`s describe the rotation of the device. +- `MagnetometerEvent`s describe the ambient magnetic field surrounding the + device. A compass is an example usage of this data. + +Each of these is exposed through a `BroadcastStream`: `accelerometerEvents`, +`userAccelerometerEvents`, `gyroscopeEvents`, and `magnetometerEvents`, +respectively. + +### Example + +```dart +import 'package:sensors_plus/sensors_plus.dart'; + +accelerometerEvents.listen((AccelerometerEvent event) { + print(event); +}); +// [AccelerometerEvent (x: 0.0, y: 9.8, z: 0.0)] + +userAccelerometerEvents.listen((UserAccelerometerEvent event) { + print(event); +}); +// [UserAccelerometerEvent (x: 0.0, y: 0.0, z: 0.0)] + +gyroscopeEvents.listen((GyroscopeEvent event) { + print(event); +}); +// [GyroscopeEvent (x: 0.0, y: 0.0, z: 0.0)] + +magnetometerEvents.listen((MagnetometerEvent event) { + print(event); +}); +// [MagnetometerEvent (x: -23.6, y: 6.2, z: -34.9)] + +``` + +Also see the `example` subdirectory for an example application that uses the +sensor data. + +Check out our website to learn more: [Plus Plugins documentation](https://plus.fluttercommunity.dev/docs/overview) diff --git a/third_party/pub_patches/sensors_plus/android/build.gradle b/third_party/pub_patches/sensors_plus/android/build.gradle new file mode 100644 index 000000000..c318a2556 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/android/build.gradle @@ -0,0 +1,50 @@ +group 'io.flutter.plugins.sensors' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 31 + + defaultConfig { + minSdkVersion 16 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = '17' + } + + dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + } +} diff --git a/third_party/pub_patches/sensors_plus/android/gradle.properties b/third_party/pub_patches/sensors_plus/android/gradle.properties new file mode 100644 index 000000000..8bd86f680 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/third_party/pub_patches/sensors_plus/android/settings.gradle b/third_party/pub_patches/sensors_plus/android/settings.gradle new file mode 100644 index 000000000..48202890d --- /dev/null +++ b/third_party/pub_patches/sensors_plus/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'sensors' diff --git a/third_party/pub_patches/sensors_plus/android/src/main/AndroidManifest.xml b/third_party/pub_patches/sensors_plus/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..36c24719f --- /dev/null +++ b/third_party/pub_patches/sensors_plus/android/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/third_party/pub_patches/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/SensorsPlugin.kt b/third_party/pub_patches/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/SensorsPlugin.kt new file mode 100644 index 000000000..34de53486 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/SensorsPlugin.kt @@ -0,0 +1,81 @@ +package dev.fluttercommunity.plus.sensors + +import android.content.Context +import android.hardware.Sensor +import android.hardware.SensorManager +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel + +/** SensorsPlugin */ +class SensorsPlugin : FlutterPlugin { + private lateinit var accelerometerChannel: EventChannel + private lateinit var userAccelChannel: EventChannel + private lateinit var gyroscopeChannel: EventChannel + private lateinit var magnetometerChannel: EventChannel + + private lateinit var accelerationStreamHandler: StreamHandlerImpl + private lateinit var linearAccelerationStreamHandler: StreamHandlerImpl + private lateinit var gyroScopeStreamHandler: StreamHandlerImpl + private lateinit var magnetometerStreamHandler: StreamHandlerImpl + + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + setupEventChannels(binding.applicationContext, binding.binaryMessenger) + } + + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + teardownEventChannels() + } + + private fun setupEventChannels(context: Context, messenger: BinaryMessenger) { + val sensorsManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager + + accelerometerChannel = EventChannel(messenger, ACCELEROMETER_CHANNEL_NAME) + accelerationStreamHandler = StreamHandlerImpl( + sensorsManager, + Sensor.TYPE_ACCELEROMETER + ) + accelerometerChannel.setStreamHandler(accelerationStreamHandler) + + userAccelChannel = EventChannel(messenger, USER_ACCELEROMETER_CHANNEL_NAME) + linearAccelerationStreamHandler = StreamHandlerImpl( + sensorsManager, + Sensor.TYPE_LINEAR_ACCELERATION + ) + userAccelChannel.setStreamHandler(linearAccelerationStreamHandler) + + gyroscopeChannel = EventChannel(messenger, GYROSCOPE_CHANNEL_NAME) + gyroScopeStreamHandler = StreamHandlerImpl( + sensorsManager, + Sensor.TYPE_GYROSCOPE + ) + gyroscopeChannel.setStreamHandler(gyroScopeStreamHandler) + + magnetometerChannel = EventChannel(messenger, MAGNETOMETER_CHANNEL_NAME) + magnetometerStreamHandler = StreamHandlerImpl( + sensorsManager, + Sensor.TYPE_MAGNETIC_FIELD + ) + magnetometerChannel.setStreamHandler(magnetometerStreamHandler) + } + + private fun teardownEventChannels() { + accelerometerChannel.setStreamHandler(null) + userAccelChannel.setStreamHandler(null) + gyroscopeChannel.setStreamHandler(null) + magnetometerChannel.setStreamHandler(null) + + accelerationStreamHandler.onCancel(null) + linearAccelerationStreamHandler.onCancel(null) + gyroScopeStreamHandler.onCancel(null) + magnetometerStreamHandler.onCancel(null) + } + + companion object { + private const val ACCELEROMETER_CHANNEL_NAME = "dev.fluttercommunity.plus/sensors/accelerometer" + private const val GYROSCOPE_CHANNEL_NAME = "dev.fluttercommunity.plus/sensors/gyroscope" + private const val USER_ACCELEROMETER_CHANNEL_NAME = "dev.fluttercommunity.plus/sensors/user_accel" + private const val MAGNETOMETER_CHANNEL_NAME = "dev.fluttercommunity.plus/sensors/magnetometer" + } +} diff --git a/third_party/pub_patches/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/StreamHandlerImpl.kt b/third_party/pub_patches/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/StreamHandlerImpl.kt new file mode 100644 index 000000000..0ac518203 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/StreamHandlerImpl.kt @@ -0,0 +1,42 @@ +package dev.fluttercommunity.plus.sensors + +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.EventChannel.EventSink + +internal class StreamHandlerImpl( + private val sensorManager: SensorManager, + sensorType: Int +) : EventChannel.StreamHandler { + private var sensorEventListener: SensorEventListener? = null + + private val sensor: Sensor by lazy { + sensorManager.getDefaultSensor(sensorType) + } + + override fun onListen(arguments: Any?, events: EventSink) { + sensorEventListener = createSensorEventListener(events) + sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL) + } + + override fun onCancel(arguments: Any?) { + sensorManager.unregisterListener(sensorEventListener) + } + + private fun createSensorEventListener(events: EventSink): SensorEventListener { + return object : SensorEventListener { + override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {} + + override fun onSensorChanged(event: SensorEvent) { + val sensorValues = DoubleArray(event.values.size) + event.values.forEachIndexed { index, value -> + sensorValues[index] = value.toDouble() + } + events.success(sensorValues) + } + } + } +} diff --git a/third_party/pub_patches/sensors_plus/example/README.md b/third_party/pub_patches/sensors_plus/example/README.md new file mode 100644 index 000000000..a0ddab647 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/README.md @@ -0,0 +1,3 @@ +# sensors_plus_example + +Demonstrates how to use the sensors_plus plugin. diff --git a/third_party/pub_patches/sensors_plus/example/android/app/build.gradle b/third_party/pub_patches/sensors_plus/example/android/app/build.gradle new file mode 100644 index 000000000..5080e7d83 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/app/build.gradle @@ -0,0 +1,60 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 31 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + applicationId "io.flutter.plugins.sensorsexample" + minSdkVersion 16 + targetSdkVersion 31 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' +} diff --git a/third_party/pub_patches/sensors_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/sensors_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..b1159fc54 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/third_party/pub_patches/sensors_plus/example/android/app/src/main/AndroidManifest.xml b/third_party/pub_patches/sensors_plus/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..ca2a768d9 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/sensors_plus/example/android/app/src/main/java/io/flutter/plugins/sensorsexample/FlutterActivityTest.java b/third_party/pub_patches/sensors_plus/example/android/app/src/main/java/io/flutter/plugins/sensorsexample/FlutterActivityTest.java new file mode 100644 index 000000000..0835b0f59 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/app/src/main/java/io/flutter/plugins/sensorsexample/FlutterActivityTest.java @@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.sensorsexample; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.integration_test.FlutterTestRunner; +import io.flutter.embedding.android.FlutterActivity; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterTestRunner.class) +public class FlutterActivityTest { + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); +} diff --git a/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..db77bb4b7 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..17987b79b Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09d439148 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5f1c8d34 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4d6372eeb Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/sensors_plus/example/android/build.gradle b/third_party/pub_patches/sensors_plus/example/android/build.gradle new file mode 100644 index 000000000..3865eb4c2 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.1' + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/third_party/pub_patches/sensors_plus/example/android/gradle.properties b/third_party/pub_patches/sensors_plus/example/android/gradle.properties new file mode 100644 index 000000000..d9cf55df7 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true diff --git a/third_party/pub_patches/sensors_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/sensors_plus/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..c17f829cd --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/third_party/pub_patches/sensors_plus/example/android/settings.gradle b/third_party/pub_patches/sensors_plus/example/android/settings.gradle new file mode 100644 index 000000000..115da6cb4 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withInputStream { stream -> plugins.load(stream) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/third_party/pub_patches/sensors_plus/example/integration_test/sensors_plus_test.dart b/third_party/pub_patches/sensors_plus/example/integration_test/sensors_plus_test.dart new file mode 100644 index 000000000..af1a3d0d0 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/integration_test/sensors_plus_test.dart @@ -0,0 +1,27 @@ +// Copyright 2019, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// @dart=2.9 + +import 'dart:async'; +import 'dart:io'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:sensors_plus/sensors_plus.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + // NOTE: The accelerometer events are not returned on iOS simulators. + testWidgets('Can subscript to accelerometerEvents and get non-null events', + (WidgetTester tester) async { + final completer = Completer(); + StreamSubscription subscription; + subscription = accelerometerEvents.listen((AccelerometerEvent event) { + completer.complete(event); + subscription.cancel(); + }); + expect(await completer.future, isNotNull); + }, skip: !Platform.isAndroid); +} diff --git a/third_party/pub_patches/sensors_plus/example/ios/Flutter/AppFrameworkInfo.plist b/third_party/pub_patches/sensors_plus/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..6c2de8086 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + UIRequiredDeviceCapabilities + + arm64 + + MinimumOSVersion + 8.0 + + diff --git a/third_party/pub_patches/sensors_plus/example/ios/Flutter/Debug.xcconfig b/third_party/pub_patches/sensors_plus/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..e8efba114 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/sensors_plus/example/ios/Flutter/Flutter.podspec b/third_party/pub_patches/sensors_plus/example/ios/Flutter/Flutter.podspec new file mode 100644 index 000000000..e689461db --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.description = <<-DESC +Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. + DESC + s.homepage = 'https://plus.fluttercommunity.dev' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Community' => 'authors@fluttercommunity.dev' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '8.0' + s.vendored_frameworks = 'Flutter.framework' +end diff --git a/third_party/pub_patches/sensors_plus/example/ios/Flutter/Release.xcconfig b/third_party/pub_patches/sensors_plus/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..399e9340e --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/project.pbxproj b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..2ee579178 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,481 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; + 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + A5B646543530B300A487D9B1 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B16C8D77F2F0873936309F38 /* libPods-Runner.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 518BFCF6A33590E963FE1FA9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 65D7779632A59CFED1723B85 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B16C8D77F2F0873936309F38 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A5B646543530B300A487D9B1 /* libPods-Runner.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5B101E38E51195F91ACE826E /* Pods */ = { + isa = PBXGroup; + children = ( + 65D7779632A59CFED1723B85 /* Pods-Runner.debug.xcconfig */, + 518BFCF6A33590E963FE1FA9 /* Pods-Runner.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 5B101E38E51195F91ACE826E /* Pods */, + DEA20432CDDA0D695086BE46 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 97C146F21CF9000F007C117D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DEA20432CDDA0D695086BE46 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B16C8D77F2F0873936309F38 /* libPods-Runner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 7B77DB2BA78582CC43C8E79F /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 2EB2E4FB0B576731DB30F0C4 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1100; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2EB2E4FB0B576731DB30F0C4 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 7B77DB2BA78582CC43C8E79F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, + 97C146F31CF9000F007C117D /* main.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.sensorsExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.sensorsExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..1d526a16e --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..3bb3697ef --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/AppDelegate.h b/third_party/pub_patches/sensors_plus/example/ios/Runner/AppDelegate.h new file mode 100644 index 000000000..36e21bbf9 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : FlutterAppDelegate + +@end diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/AppDelegate.m b/third_party/pub_patches/sensors_plus/example/ios/Runner/AppDelegate.m new file mode 100644 index 000000000..352291d2f --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner/AppDelegate.m @@ -0,0 +1,14 @@ +#include "AppDelegate.h" +#include "GeneratedPluginRegistrant.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + // Override point for customization after application launch. + return [super application:application + didFinishLaunchingWithOptions:launchOptions]; +} + +@end diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d22f10b2a --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 000000000..28c6bf030 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 000000000..f091b6b0b Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 000000000..4cde12118 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 000000000..d0ef06e7e Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 000000000..dcdc2306c Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 000000000..c8f9ed8f5 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 000000000..75b2d164a Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 000000000..c4df70d39 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 000000000..6a84f41e1 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 000000000..d0e1f5853 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/third_party/pub_patches/sensors_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..ebf48f603 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Base.lproj/Main.storyboard b/third_party/pub_patches/sensors_plus/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/Info.plist b/third_party/pub_patches/sensors_plus/example/ios/Runner/Info.plist new file mode 100644 index 000000000..bc49e9088 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + sensors_example + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/third_party/pub_patches/sensors_plus/example/ios/Runner/main.m b/third_party/pub_patches/sensors_plus/example/ios/Runner/main.m new file mode 100644 index 000000000..5b8c35f9d --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/ios/Runner/main.m @@ -0,0 +1,10 @@ +#import "AppDelegate.h" +#import +#import + +int main(int argc, char *argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, + NSStringFromClass([AppDelegate class])); + } +} diff --git a/third_party/pub_patches/sensors_plus/example/lib/main.dart b/third_party/pub_patches/sensors_plus/example/lib/main.dart new file mode 100644 index 000000000..77b686a94 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/lib/main.dart @@ -0,0 +1,176 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:sensors_plus/sensors_plus.dart'; + +import 'snake.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Sensors Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, this.title}) : super(key: key); + + final String? title; + + @override + _MyHomePageState createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + static const int _snakeRows = 20; + static const int _snakeColumns = 20; + static const double _snakeCellSize = 10.0; + + List? _accelerometerValues; + List? _userAccelerometerValues; + List? _gyroscopeValues; + List? _magnetometerValues; + final _streamSubscriptions = >[]; + + @override + Widget build(BuildContext context) { + final accelerometer = + _accelerometerValues?.map((double v) => v.toStringAsFixed(1)).toList(); + final gyroscope = + _gyroscopeValues?.map((double v) => v.toStringAsFixed(1)).toList(); + final userAccelerometer = _userAccelerometerValues + ?.map((double v) => v.toStringAsFixed(1)) + .toList(); + final magnetometer = + _magnetometerValues?.map((double v) => v.toStringAsFixed(1)).toList(); + + return Scaffold( + appBar: AppBar( + title: const Text('Sensor Example'), + ), + body: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Center( + child: DecoratedBox( + decoration: BoxDecoration( + border: Border.all(width: 1.0, color: Colors.black38), + ), + child: SizedBox( + height: _snakeRows * _snakeCellSize, + width: _snakeColumns * _snakeCellSize, + child: Snake( + rows: _snakeRows, + columns: _snakeColumns, + cellSize: _snakeCellSize, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Accelerometer: $accelerometer'), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('UserAccelerometer: $userAccelerometer'), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Gyroscope: $gyroscope'), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Magnetometer: $magnetometer'), + ], + ), + ), + ], + ), + ); + } + + @override + void dispose() { + super.dispose(); + for (final subscription in _streamSubscriptions) { + subscription.cancel(); + } + } + + @override + void initState() { + super.initState(); + _streamSubscriptions.add( + accelerometerEvents.listen( + (AccelerometerEvent event) { + setState(() { + _accelerometerValues = [event.x, event.y, event.z]; + }); + }, + ), + ); + _streamSubscriptions.add( + gyroscopeEvents.listen( + (GyroscopeEvent event) { + setState(() { + _gyroscopeValues = [event.x, event.y, event.z]; + }); + }, + ), + ); + _streamSubscriptions.add( + userAccelerometerEvents.listen( + (UserAccelerometerEvent event) { + setState(() { + _userAccelerometerValues = [event.x, event.y, event.z]; + }); + }, + ), + ); + _streamSubscriptions.add( + magnetometerEvents.listen( + (MagnetometerEvent event) { + setState(() { + _magnetometerValues = [event.x, event.y, event.z]; + }); + }, + ), + ); + } +} diff --git a/third_party/pub_patches/sensors_plus/example/lib/snake.dart b/third_party/pub_patches/sensors_plus/example/lib/snake.dart new file mode 100644 index 000000000..0b4d18b66 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/lib/snake.dart @@ -0,0 +1,132 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:sensors_plus/sensors_plus.dart'; + +class Snake extends StatefulWidget { + Snake({Key? key, this.rows = 20, this.columns = 20, this.cellSize = 10.0}) + : super(key: key) { + assert(10 <= rows); + assert(10 <= columns); + assert(5.0 <= cellSize); + } + + final int rows; + final int columns; + final double cellSize; + + @override + // ignore: no_logic_in_create_state + State createState() => SnakeState(rows, columns, cellSize); +} + +class SnakeBoardPainter extends CustomPainter { + SnakeBoardPainter(this.state, this.cellSize); + + GameState? state; + double cellSize; + + @override + void paint(Canvas canvas, Size size) { + final blackLine = Paint()..color = Colors.black; + final blackFilled = Paint() + ..color = Colors.black + ..style = PaintingStyle.fill; + canvas.drawRect( + Rect.fromPoints(Offset.zero, size.bottomLeft(Offset.zero)), + blackLine, + ); + for (final p in state!.body) { + final a = Offset(cellSize * p.x, cellSize * p.y); + final b = Offset(cellSize * (p.x + 1), cellSize * (p.y + 1)); + + canvas.drawRect(Rect.fromPoints(a, b), blackFilled); + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} + +class SnakeState extends State { + SnakeState(int rows, int columns, this.cellSize) { + state = GameState(rows, columns); + } + + double cellSize; + GameState? state; + AccelerometerEvent? acceleration; + late StreamSubscription _streamSubscription; + late Timer _timer; + + @override + Widget build(BuildContext context) { + return CustomPaint(painter: SnakeBoardPainter(state, cellSize)); + } + + @override + void dispose() { + super.dispose(); + _streamSubscription.cancel(); + _timer.cancel(); + } + + @override + void initState() { + super.initState(); + _streamSubscription = + accelerometerEvents.listen((AccelerometerEvent event) { + setState(() { + acceleration = event; + }); + }); + + _timer = Timer.periodic(const Duration(milliseconds: 200), (_) { + setState(() { + _step(); + }); + }); + } + + void _step() { + final newDirection = acceleration == null + ? null + : acceleration!.x.abs() < 1.0 && acceleration!.y.abs() < 1.0 + ? null + : (acceleration!.x.abs() < acceleration!.y.abs()) + ? math.Point(0, acceleration!.y.sign.toInt()) + : math.Point(-acceleration!.x.sign.toInt(), 0); + state!.step(newDirection); + } +} + +class GameState { + GameState(this.rows, this.columns) { + snakeLength = math.min(rows, columns) - 5; + } + + int rows; + int columns; + late int snakeLength; + + List> body = >[const math.Point(0, 0)]; + math.Point direction = const math.Point(1, 0); + + void step(math.Point? newDirection) { + var next = body.last + direction; + next = math.Point(next.x % columns, next.y % rows); + + body.add(next); + if (body.length > snakeLength) body.removeAt(0); + direction = newDirection ?? direction; + } +} diff --git a/third_party/pub_patches/sensors_plus/example/pubspec.yaml b/third_party/pub_patches/sensors_plus/example/pubspec.yaml new file mode 100644 index 000000000..1c3c06e87 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/pubspec.yaml @@ -0,0 +1,28 @@ +name: sensors_plus_example +description: Demonstrates how to use the sensors plugin. + +dependencies: + flutter: + sdk: flutter + sensors_plus: + path: ../ + +dependency_overrides: + sensors_plus_platform_interface: + path: ../../sensors_plus_platform_interface + sensors_plus_web: + path: ../../sensors_plus_web + +dev_dependencies: + flutter_driver: + sdk: flutter + integration_test: + sdk: flutter + flutter_lints: ^1.0.4 + +flutter: + uses-material-design: true + +environment: + sdk: '>=2.12.0 <3.0.0' + flutter: ">=1.9.1+hotfix.2" diff --git a/third_party/pub_patches/sensors_plus/example/web/favicon.png b/third_party/pub_patches/sensors_plus/example/web/favicon.png new file mode 100644 index 000000000..8aaa46ac1 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/web/favicon.png differ diff --git a/third_party/pub_patches/sensors_plus/example/web/icons/Icon-192.png b/third_party/pub_patches/sensors_plus/example/web/icons/Icon-192.png new file mode 100644 index 000000000..b749bfef0 Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/web/icons/Icon-192.png differ diff --git a/third_party/pub_patches/sensors_plus/example/web/icons/Icon-512.png b/third_party/pub_patches/sensors_plus/example/web/icons/Icon-512.png new file mode 100644 index 000000000..88cfd48df Binary files /dev/null and b/third_party/pub_patches/sensors_plus/example/web/icons/Icon-512.png differ diff --git a/third_party/pub_patches/sensors_plus/example/web/index.html b/third_party/pub_patches/sensors_plus/example/web/index.html new file mode 100644 index 000000000..2022dbf1d --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/third_party/pub_patches/sensors_plus/example/web/manifest.json b/third_party/pub_patches/sensors_plus/example/web/manifest.json new file mode 100644 index 000000000..beeb46b0a --- /dev/null +++ b/third_party/pub_patches/sensors_plus/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "Flutter Sensors Plus example", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/third_party/pub_patches/sensors_plus/ios/Classes/FLTSensorsPlusPlugin.h b/third_party/pub_patches/sensors_plus/ios/Classes/FLTSensorsPlusPlugin.h new file mode 100644 index 000000000..70e48f9d9 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/ios/Classes/FLTSensorsPlusPlugin.h @@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface FLTSensorsPlusPlugin : NSObject +@end + +@interface FLTUserAccelStreamHandlerPlus : NSObject +@end + +@interface FLTAccelerometerStreamHandlerPlus : NSObject +@end + +@interface FLTGyroscopeStreamHandlerPlus : NSObject +@end + +@interface FLTMagnetometerStreamHandlerPlus : NSObject +@end diff --git a/third_party/pub_patches/sensors_plus/ios/Classes/FLTSensorsPlusPlugin.m b/third_party/pub_patches/sensors_plus/ios/Classes/FLTSensorsPlusPlugin.m new file mode 100644 index 000000000..11b63e809 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/ios/Classes/FLTSensorsPlusPlugin.m @@ -0,0 +1,255 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FLTSensorsPlusPlugin.h" +#import + +@implementation FLTSensorsPlusPlugin + +NSMutableDictionary *_eventChannels; +NSMutableDictionary *> + *_streamHandlers; +BOOL _isCleanUp = NO; + ++ (void)registerWithRegistrar:(NSObject *)registrar { + _eventChannels = [NSMutableDictionary dictionary]; + _streamHandlers = [NSMutableDictionary dictionary]; + + FLTAccelerometerStreamHandlerPlus *accelerometerStreamHandler = + [[FLTAccelerometerStreamHandlerPlus alloc] init]; + NSString *accelerometerStreamHandlerName = + @"dev.fluttercommunity.plus/sensors/accelerometer"; + FlutterEventChannel *accelerometerChannel = + [FlutterEventChannel eventChannelWithName:accelerometerStreamHandlerName + binaryMessenger:[registrar messenger]]; + [accelerometerChannel setStreamHandler:accelerometerStreamHandler]; + [_eventChannels setObject:accelerometerChannel + forKey:accelerometerStreamHandlerName]; + [_streamHandlers setObject:accelerometerStreamHandler + forKey:accelerometerStreamHandlerName]; + + FLTUserAccelStreamHandlerPlus *userAccelerometerStreamHandler = + [[FLTUserAccelStreamHandlerPlus alloc] init]; + NSString *userAccelerometerStreamHandlerName = + @"dev.fluttercommunity.plus/sensors/user_accel"; + FlutterEventChannel *userAccelerometerChannel = [FlutterEventChannel + eventChannelWithName:userAccelerometerStreamHandlerName + binaryMessenger:[registrar messenger]]; + [userAccelerometerChannel setStreamHandler:userAccelerometerStreamHandler]; + [_eventChannels setObject:userAccelerometerChannel + forKey:userAccelerometerStreamHandlerName]; + [_streamHandlers setObject:userAccelerometerStreamHandler + forKey:accelerometerStreamHandlerName]; + + FLTGyroscopeStreamHandlerPlus *gyroscopeStreamHandler = + [[FLTGyroscopeStreamHandlerPlus alloc] init]; + NSString *gyroscopeStreamHandlerName = + @"dev.fluttercommunity.plus/sensors/gyroscope"; + FlutterEventChannel *gyroscopeChannel = + [FlutterEventChannel eventChannelWithName:gyroscopeStreamHandlerName + binaryMessenger:[registrar messenger]]; + [gyroscopeChannel setStreamHandler:gyroscopeStreamHandler]; + [_eventChannels setObject:gyroscopeChannel forKey:gyroscopeStreamHandlerName]; + [_streamHandlers setObject:gyroscopeStreamHandler + forKey:accelerometerStreamHandlerName]; + + FLTMagnetometerStreamHandlerPlus *magnetometerStreamHandler = + [[FLTMagnetometerStreamHandlerPlus alloc] init]; + NSString *magnetometerStreamHandlerName = + @"dev.fluttercommunity.plus/sensors/magnetometer"; + FlutterEventChannel *magnetometerChannel = + [FlutterEventChannel eventChannelWithName:magnetometerStreamHandlerName + binaryMessenger:[registrar messenger]]; + [magnetometerChannel setStreamHandler:magnetometerStreamHandler]; + [_eventChannels setObject:magnetometerChannel + forKey:magnetometerStreamHandlerName]; + [_streamHandlers setObject:magnetometerStreamHandler + forKey:accelerometerStreamHandlerName]; + + _isCleanUp = NO; +} + +- (void)detachFromEngineForRegistrar: + (NSObject *)registrar { + _cleanUp(); +} + +static void _cleanUp() { + _isCleanUp = YES; + for (FlutterEventChannel *channel in _eventChannels.allValues) { + [channel setStreamHandler:nil]; + } + [_eventChannels removeAllObjects]; + for (NSObject *handler in _streamHandlers.allValues) { + [handler onCancelWithArguments:nil]; + } + [_streamHandlers removeAllObjects]; +} + +@end + +const double GRAVITY = 9.8; +CMMotionManager *_motionManager; + +void _initMotionManager(void) { + if (!_motionManager) { + _motionManager = [[CMMotionManager alloc] init]; + } +} + +static void sendTriplet(Float64 x, Float64 y, Float64 z, + FlutterEventSink sink) { + if (_isCleanUp) { + return; + } + // Even after [detachFromEngineForRegistrar] some events may still be received + // and fired until fully detached. + @try { + NSMutableData *event = [NSMutableData dataWithCapacity:3 * sizeof(Float64)]; + [event appendBytes:&x length:sizeof(Float64)]; + [event appendBytes:&y length:sizeof(Float64)]; + [event appendBytes:&z length:sizeof(Float64)]; + + sink([FlutterStandardTypedData typedDataWithFloat64:event]); + } @catch (NSException *e) { + NSLog(@"Error: %@ %@", e, [e userInfo]); + } @finally { + } +} + +@implementation FLTAccelerometerStreamHandlerPlus + +- (FlutterError *)onListenWithArguments:(id)arguments + eventSink:(FlutterEventSink)eventSink { + _initMotionManager(); + [_motionManager + startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] + withHandler:^(CMAccelerometerData *accelerometerData, + NSError *error) { + CMAcceleration acceleration = + accelerometerData.acceleration; + // Multiply by gravity, and adjust sign values to + // align with Android. + if (_isCleanUp) { + return; + } + sendTriplet(-acceleration.x * GRAVITY, + -acceleration.y * GRAVITY, + -acceleration.z * GRAVITY, eventSink); + }]; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + [_motionManager stopAccelerometerUpdates]; + return nil; +} + +- (void)dealloc { + _cleanUp(); +} + +@end + +@implementation FLTUserAccelStreamHandlerPlus + +- (FlutterError *)onListenWithArguments:(id)arguments + eventSink:(FlutterEventSink)eventSink { + _initMotionManager(); + [_motionManager + startDeviceMotionUpdatesToQueue:[[NSOperationQueue alloc] init] + withHandler:^(CMDeviceMotion *data, NSError *error) { + CMAcceleration acceleration = data.userAcceleration; + // Multiply by gravity, and adjust sign values to + // align with Android. + if (_isCleanUp) { + return; + } + sendTriplet(-acceleration.x * GRAVITY, + -acceleration.y * GRAVITY, + -acceleration.z * GRAVITY, eventSink); + }]; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + [_motionManager stopDeviceMotionUpdates]; + return nil; +} + +- (void)dealloc { + _cleanUp(); +} + +@end + +@implementation FLTGyroscopeStreamHandlerPlus + +- (FlutterError *)onListenWithArguments:(id)arguments + eventSink:(FlutterEventSink)eventSink { + _initMotionManager(); + [_motionManager + startGyroUpdatesToQueue:[[NSOperationQueue alloc] init] + withHandler:^(CMGyroData *gyroData, NSError *error) { + CMRotationRate rotationRate = gyroData.rotationRate; + if (_isCleanUp) { + return; + } + sendTriplet(rotationRate.x, rotationRate.y, rotationRate.z, + eventSink); + }]; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + [_motionManager stopGyroUpdates]; + return nil; +} + +- (void)dealloc { + _cleanUp(); +} + +@end + +@implementation FLTMagnetometerStreamHandlerPlus + +- (FlutterError *)onListenWithArguments:(id)arguments + eventSink:(FlutterEventSink)eventSink { + _initMotionManager(); + // Allow iOS to present calibration interaction. + _motionManager.showsDeviceMovementDisplay = YES; + [_motionManager + startDeviceMotionUpdatesUsingReferenceFrame: + // https://developer.apple.com/documentation/coremotion/cmattitudereferenceframe?language=objc + // "Using this reference frame may require device movement to + // calibrate the magnetometer," which is desired to ensure the + // DeviceMotion actually has updated, calibrated geomagnetic data. + CMAttitudeReferenceFrameXMagneticNorthZVertical + toQueue:[[NSOperationQueue alloc] + init] + withHandler:^(CMDeviceMotion *motionData, + NSError *error) { + // The `magneticField` is a + // CMCalibratedMagneticField. + CMMagneticField b = + motionData.magneticField.field; + if (_isCleanUp) { + return; + } + sendTriplet(b.x, b.y, b.z, eventSink); + }]; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + [_motionManager stopDeviceMotionUpdates]; + return nil; +} + +- (void)dealloc { + _cleanUp(); +} + +@end diff --git a/third_party/pub_patches/sensors_plus/ios/sensors_plus.podspec b/third_party/pub_patches/sensors_plus/ios/sensors_plus.podspec new file mode 100644 index 000000000..1c593746f --- /dev/null +++ b/third_party/pub_patches/sensors_plus/ios/sensors_plus.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'sensors_plus' + s.version = '0.0.1' + s.summary = 'Flutter Sensors' + s.description = <<-DESC +Flutter plugin to access the accelerometer, gyroscope, and magnetometer sensors. + DESC + s.homepage = 'https://github.com/flutter/plugins' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :http => 'https://github.com/flutter/plugins/tree/main/packages/sensors' } + s.documentation_url = 'https://pub.dev/packages/sensors' + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + + s.platform = :ios, '8.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } +end diff --git a/third_party/pub_patches/sensors_plus/lib/sensors_plus.dart b/third_party/pub_patches/sensors_plus/lib/sensors_plus.dart new file mode 100644 index 000000000..1ace1d961 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/lib/sensors_plus.dart @@ -0,0 +1,28 @@ +export 'src/sensors.dart'; + +import 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart'; + +import 'src/sensors.dart'; +export 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart'; + +final _sensors = Sensors(); + +/// A broadcast stream of events from the device accelerometer. +Stream get accelerometerEvents { + return _sensors.accelerometerEvents; +} + +/// A broadcast stream of events from the device gyroscope. +Stream get gyroscopeEvents { + return _sensors.gyroscopeEvents; +} + +/// Events from the device accelerometer with gravity removed. +Stream get userAccelerometerEvents { + return _sensors.userAccelerometerEvents; +} + +/// A broadcast stream of events from the device magnetometer. +Stream get magnetometerEvents { + return _sensors.magnetometerEvents; +} diff --git a/third_party/pub_patches/sensors_plus/lib/src/sensors.dart b/third_party/pub_patches/sensors_plus/lib/src/sensors.dart new file mode 100644 index 000000000..59ac78cb8 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/lib/src/sensors.dart @@ -0,0 +1,39 @@ +import 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart'; + +/// The Sensors implementation. +class Sensors extends SensorsPlatform { + /// Constructs a singleton instance of [Sensors]. + /// + /// [Sensors] is designed to work as a singleton. + factory Sensors() => _singleton ??= Sensors._(); + + Sensors._(); + + static Sensors? _singleton; + + static SensorsPlatform get _platform => SensorsPlatform.instance; + + /// A broadcast stream of events from the device accelerometer. + @override + Stream get accelerometerEvents { + return _platform.accelerometerEvents; + } + + /// A broadcast stream of events from the device gyroscope. + @override + Stream get gyroscopeEvents { + return _platform.gyroscopeEvents; + } + + /// Events from the device accelerometer with gravity removed. + @override + Stream get userAccelerometerEvents { + return _platform.userAccelerometerEvents; + } + + /// A broadcast stream of events from the device magnetometer. + @override + Stream get magnetometerEvents { + return _platform.magnetometerEvents; + } +} diff --git a/third_party/pub_patches/sensors_plus/pubspec.yaml b/third_party/pub_patches/sensors_plus/pubspec.yaml new file mode 100644 index 000000000..44199d2a3 --- /dev/null +++ b/third_party/pub_patches/sensors_plus/pubspec.yaml @@ -0,0 +1,33 @@ +name: sensors_plus +description: Flutter plugin for accessing accelerometer, gyroscope, and + magnetometer sensors. +version: 1.4.1 +homepage: https://plus.fluttercommunity.dev/ +repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/ +issue_tracker: https://github.com/fluttercommunity/plus_plugins/labels/sensors_plus + +flutter: + plugin: + platforms: + android: + package: dev.fluttercommunity.plus.sensors + pluginClass: SensorsPlugin + ios: + pluginClass: FLTSensorsPlusPlugin + web: + default_package: sensors_plus_web + +dependencies: + flutter: + sdk: flutter + sensors_plus_web: ^1.1.2 + sensors_plus_platform_interface: ^1.1.2 +dev_dependencies: + test: ^1.16.4 + flutter_test: + sdk: flutter + flutter_lints: ^2.0.1 + +environment: + sdk: ">=2.12.0 <3.0.0" + flutter: ">=1.12.13+hotfix.5" diff --git a/third_party/pub_patches/sensors_plus/test/sensors_test.dart b/third_party/pub_patches/sensors_plus/test/sensors_test.dart new file mode 100644 index 000000000..0dea6a11c --- /dev/null +++ b/third_party/pub_patches/sensors_plus/test/sensors_test.dart @@ -0,0 +1,87 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart' + show TestDefaultBinaryMessengerBinding, TestWidgetsFlutterBinding; +import 'package:sensors_plus/sensors_plus.dart'; +import 'package:test/test.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + test('$accelerometerEvents are streamed', () async { + const channelName = 'dev.fluttercommunity.plus/sensors/accelerometer'; + const sensorData = [1.0, 2.0, 3.0]; + _initializeFakeSensorChannel(channelName, sensorData); + + final event = await accelerometerEvents.first; + + expect(event.x, sensorData[0]); + expect(event.y, sensorData[1]); + expect(event.z, sensorData[2]); + }); + + test('$gyroscopeEvents are streamed', () async { + const channelName = 'dev.fluttercommunity.plus/sensors/gyroscope'; + const sensorData = [3.0, 4.0, 5.0]; + _initializeFakeSensorChannel(channelName, sensorData); + + final event = await gyroscopeEvents.first; + + expect(event.x, sensorData[0]); + expect(event.y, sensorData[1]); + expect(event.z, sensorData[2]); + }); + + test('$userAccelerometerEvents are streamed', () async { + const channelName = 'dev.fluttercommunity.plus/sensors/user_accel'; + const sensorData = [6.0, 7.0, 8.0]; + _initializeFakeSensorChannel(channelName, sensorData); + + final event = await userAccelerometerEvents.first; + + expect(event.x, sensorData[0]); + expect(event.y, sensorData[1]); + expect(event.z, sensorData[2]); + }); + + test('$magnetometerEvents are streamed', () async { + const channelName = 'dev.fluttercommunity.plus/sensors/magnetometer'; + const sensorData = [8.0, 9.0, 10.0]; + _initializeFakeSensorChannel(channelName, sensorData); + + final event = await magnetometerEvents.first; + + expect(event.x, sensorData[0]); + expect(event.y, sensorData[1]); + expect(event.z, sensorData[2]); + }); +} + +void _initializeFakeSensorChannel(String channelName, List sensorData) { + const standardMethod = StandardMethodCodec(); + + void emitEvent(ByteData? event) { + ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + channelName, + event, + (ByteData? reply) {}, + ); + } + + TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger + .setMockMessageHandler(channelName, (ByteData? message) async { + final methodCall = standardMethod.decodeMethodCall(message); + if (methodCall.method == 'listen') { + emitEvent(standardMethod.encodeSuccessEnvelope(sensorData)); + emitEvent(null); + return standardMethod.encodeSuccessEnvelope(null); + } else if (methodCall.method == 'cancel') { + return standardMethod.encodeSuccessEnvelope(null); + } else { + fail('Expected listen or cancel'); + } + }); +} diff --git a/third_party/pub_patches/vibration/CHANGELOG.md b/third_party/pub_patches/vibration/CHANGELOG.md new file mode 100644 index 000000000..eddce8159 --- /dev/null +++ b/third_party/pub_patches/vibration/CHANGELOG.md @@ -0,0 +1,106 @@ +## 1.9.0 + +- Added OpenHarmony support +- Migrate to common platform implement (vibration_platform_interface) + +## 1.8.4 + +- Added Web support (#95 by [san-smith](https://github.com/san-smith)) + +## 1.8.2 + +- Raise minimum and target SDK versions for Android to upgrade Gradle to 7.5. + +## 1.8.0 + +- Use `device_info_plus` for `hasAmplitudeControl` and `hasVibrator` methods. + +## 1.7.7 + +- Adds a namespace attribute to the Android build.gradle, for compatibility with Android Gradle Plugin 8.0. + +## 1.7.6 + +- Update package's dart SDK max version (under 3.0.0) + +## 1.7.5 + +- Bump `vibration_web` to 1.6.4. + +## 1.7.4 + +- Migrating to null safety. + +## 1.7.3 + +- Use targetEnvironment check on iOS. + +## 1.7.2 + +- Updated description to indicate web support. + +## 1.7.1 + +- Fix building on iOS. + +## 1.7.0 + +- Use Android Embedding v2. + +## 1.6.1 + +- Added Web support (#43 by [roulljdh](https://github.com/roulljdh)) + +## 1.5.0 + +- Fibration now works in backgroud on Android (#40 by [wanghaiyang5241](https://github.com/wanghaiyang5241)) + +## 1.4.0 + +- Added a `hasCustomVibrationsSupport` method (#34 by [Skyost](https://github.com/Skyost)) +- Use Swift 5.0 + +## 1.3.1 + +- Fix #32 (by [Hugo Heneault](https://github.com/HugoHeneault)) + +## 1.3.0 + +- Add support for CoreHaptics on iOS devices #30 (by [Leicas](https://github.com/Leicas)) + +## 1.2.4 + +- Move `flutter_test` to dev_dependencies. Fixes issue #24. + +## 1.2.3 + +- Add proper indication of async methods to docs (by [@qqgg231](https://github.com/qqgg231)) + +## 1.2.2 + +- Suppress deprecation warnings for `vibrate` method + +## 1.2.1 + +- Maintenance release + +## 1.2.0 + +- Add support for amplitude control under Android 8.0 and later (by [@pmundt](https://github.com/pmundt)) + +## 1.1.0 + +- Migrate to AndroidX (by [@gastonmuijtjens](https://github.com/gastonmuijtjens)) +- Add unit test for canceling vibration (by [@vintage](https://github.com/vintage)) + +## 1.0.2 + +- Update vibration.podspec + +## 1.0.1 + +- Implemented `cancel` method for iOS + +## 1.0.0 + +- Initial Release diff --git a/third_party/pub_patches/vibration/LICENSE b/third_party/pub_patches/vibration/LICENSE new file mode 100644 index 000000000..1ddb0c38a --- /dev/null +++ b/third_party/pub_patches/vibration/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2018, Benjamin Dean +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/pub_patches/vibration/README.md b/third_party/pub_patches/vibration/README.md new file mode 100644 index 000000000..52b1f1acc --- /dev/null +++ b/third_party/pub_patches/vibration/README.md @@ -0,0 +1,151 @@ +# Vibration + +[![Build Status](https://travis-ci.org/benjamindean/flutter_vibration.svg?branch=master)](https://travis-ci.org/benjamindean/flutter_vibration) + +A plugin for handling Vibration API on iOS, Android, and web. [API docs.](https://pub.dartlang.org/documentation/vibration/latest/vibration/Vibration-class.html) + +## Getting Started + +1. Add `vibration` to the dependencies section of `pubspec.yaml`. + + ``` yml + dependencies: + vibration: ^1.8.4 + ``` + +2. Import package: + + ``` dart + import 'package:vibration/vibration.dart'; + ``` + +## Methods + +### hasVibrator + +Check if the target device has vibration capabilities. + +``` dart +if (await Vibration.hasVibrator()) { + Vibration.vibrate(); +} +``` + +### hasAmplitudeControl + +Check if the target device has the ability to control the vibration amplitude, +introduced in Android 8.0 Oreo - false for all earlier API levels. + +``` dart +if (await Vibration.hasAmplitudeControl()) { + Vibration.vibrate(amplitude: 128); +} +``` + +### hasCustomVibrationsSupport + +Check if the device is able to vibrate with a custom duration, pattern or intensity. +May return `true` even if the device has no vibrator (if you want to check whether the device has a vibrator, +see [`hasVibrator`](#hasVibrator)). + +```dart +if (await Vibration.hasCustomVibrationsSupport()) { + Vibration.vibrate(duration: 1000); +} else { + Vibration.vibrate(); + await Future.delayed(Duration(milliseconds: 500)); + Vibration.vibrate(); +} +``` + +### vibrate + +#### With specific duration (for example, 1 second): + +``` dart +Vibration.vibrate(duration: 1000); +``` + +Default duration is 500ms. + +#### With specific duration and specific amplitude (if supported): + +``` dart +Vibration.vibrate(duration: 1000, amplitude: 128); +``` + +#### With pattern (wait 500ms, vibrate 1s, wait 500ms, vibrate 2s): + +``` dart +Vibration.vibrate(pattern: [500, 1000, 500, 2000]); +``` + +#### With pattern (wait 500ms, vibrate 1s, wait 500ms, vibrate 2s) at varying intensities (1 - min, 255 - max): + +``` dart +Vibration.vibrate(pattern: [500, 1000, 500, 2000], intensities: [1, 255]); +``` + +### cancel + +Stop ongoing vibration. + +``` dart +Vibration.cancel(); +``` + +## Android + +The `VIBRATE` permission is required in AndroidManifest.xml. + +``` xml + +``` + +Supports vibration with duration and pattern. On Android 8 (Oreo) and above, uses the [VibrationEffect](https://developer.android.com/reference/android/os/VibrationEffect) class. +For the rest of the usage instructions, see [Vibrator](https://developer.android.com/reference/android/os/Vibrator) class documentation. + +## iOS + +Supports vibration with duration and pattern on CoreHaptics devices. On older devices, the pattern is emulated with 500ms long vibrations. +You can check whether the current device has CoreHaptics support using [`hasCustomVibrationsSupport`](#hasCustomVibrationsSupport). + + +## OpenHarmony + +The OpenHarmony implementation of [`vibration`][1]. + +[`vibration`][1] 在 OpenHarmony 平台的实现。 + + +Add the following permission settings to your project's module.json5 file. + +在你的项目的 `module.json5` 文件中增加以下权限设置。 + +```json + "requestPermissions": [ + {"name" : "ohos.permission.VIBRATE"}, + ] +``` + +## Usage + +```yaml +dependencies: + vibration: any + vibration_ohos: any +``` + +`vibrateEffect` and `vibrateAttribute` are only exist in `VibrationOhos`. + + +```dart + (VibrationPlatform.instance as VibrationOhos).vibrate( + vibrateEffect: const VibratePreset(count: 100), + vibrateAttribute: const VibrateAttribute( + usage: 'alarm', + ), + ); +``` + + [1]: https://pub.dev/packages/vibration \ No newline at end of file diff --git a/third_party/pub_patches/vibration/android/build.gradle b/third_party/pub_patches/vibration/android/build.gradle new file mode 100644 index 000000000..db9965b8a --- /dev/null +++ b/third_party/pub_patches/vibration/android/build.gradle @@ -0,0 +1,35 @@ +group 'com.benjaminabel.vibration' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.4.0' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' + +android { + namespace 'com.benjaminabel.vibration' + compileSdkVersion 33 + + defaultConfig { + minSdkVersion 19 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +} diff --git a/third_party/pub_patches/vibration/android/gradle.properties b/third_party/pub_patches/vibration/android/gradle.properties new file mode 100644 index 000000000..38c8d4544 --- /dev/null +++ b/third_party/pub_patches/vibration/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/third_party/pub_patches/vibration/android/gradle/wrapper/gradle-wrapper.jar b/third_party/pub_patches/vibration/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..13372aef5 Binary files /dev/null and b/third_party/pub_patches/vibration/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/third_party/pub_patches/vibration/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/vibration/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..3c472b99c --- /dev/null +++ b/third_party/pub_patches/vibration/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/third_party/pub_patches/vibration/android/settings.gradle b/third_party/pub_patches/vibration/android/settings.gradle new file mode 100644 index 000000000..9b3dadb16 --- /dev/null +++ b/third_party/pub_patches/vibration/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'vibration' diff --git a/third_party/pub_patches/vibration/android/src/main/AndroidManifest.xml b/third_party/pub_patches/vibration/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..1f2b357ce --- /dev/null +++ b/third_party/pub_patches/vibration/android/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + diff --git a/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/Vibration.java b/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/Vibration.java new file mode 100644 index 000000000..eee111bc3 --- /dev/null +++ b/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/Vibration.java @@ -0,0 +1,93 @@ +package com.benjaminabel.vibration; + +import android.os.Build; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.media.AudioAttributes; + +import java.util.List; + +public class Vibration { + private final Vibrator vibrator; + + Vibration(Vibrator vibrator) { + this.vibrator = vibrator; + } + + @SuppressWarnings("deprecation") + void vibrate(long duration, int amplitude) { + if (vibrator.hasVibrator()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (vibrator.hasAmplitudeControl()) { + vibrator.vibrate(VibrationEffect.createOneShot(duration, amplitude), new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM) + .build()); + } else { + vibrator.vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE), new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM) + .build()); + } + } else { + vibrator.vibrate(duration); + } + } + } + + @SuppressWarnings("deprecation") + void vibrate(List pattern, int repeat) { + long[] patternLong = new long[pattern.size()]; + + for (int i = 0; i < patternLong.length; i++) { + patternLong[i] = pattern.get(i).intValue(); + } + + if (vibrator.hasVibrator()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + vibrator.vibrate(VibrationEffect.createWaveform(patternLong, repeat), new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM) + .build()); + } else { + vibrator.vibrate(patternLong, repeat); + } + } + } + + @SuppressWarnings("deprecation") + void vibrate(List pattern, int repeat, List intensities) { + long[] patternLong = new long[pattern.size()]; + int[] intensitiesArray = new int[intensities.size()]; + + for (int i = 0; i < patternLong.length; i++) { + patternLong[i] = pattern.get(i).intValue(); + } + + for (int i = 0; i < intensitiesArray.length; i++) { + intensitiesArray[i] = intensities.get(i); + } + + if (vibrator.hasVibrator()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (vibrator.hasAmplitudeControl()) { + vibrator.vibrate(VibrationEffect.createWaveform(patternLong, intensitiesArray, repeat), new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM) + .build()); + } else { + vibrator.vibrate(VibrationEffect.createWaveform(patternLong, repeat), new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM) + .build()); + } + } else { + vibrator.vibrate(patternLong, repeat); + } + } + } + + Vibrator getVibrator() { + return this.vibrator; + } +} \ No newline at end of file diff --git a/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/VibrationMethodChannelHandler.java b/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/VibrationMethodChannelHandler.java new file mode 100644 index 000000000..130077dde --- /dev/null +++ b/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/VibrationMethodChannelHandler.java @@ -0,0 +1,64 @@ +package com.benjaminabel.vibration; + +import android.os.Build; + +import java.util.List; + +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; + +class VibrationMethodChannelHandler implements MethodChannel.MethodCallHandler { + private final Vibration vibration; + + VibrationMethodChannelHandler(Vibration vibrationPlugin) { + assert (vibrationPlugin != null); + this.vibration = vibrationPlugin; + } + + @Override + public void onMethodCall(MethodCall call, MethodChannel.Result result) { + switch (call.method) { + case "hasAmplitudeControl": + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + result.success(vibration.getVibrator().hasAmplitudeControl()); + } else { + // For earlier API levels, return false rather than raising a + // MissingPluginException in order to allow applications to handle + // non-existence gracefully. + result.success(false); + } + + break; + case "hasCustomVibrationsSupport": + result.success(true); + + break; + case "vibrate": + int duration = call.argument("duration"); + List pattern = call.argument("pattern"); + int repeat = call.argument("repeat"); + List intensities = call.argument("intensities"); + int amplitude = call.argument("amplitude"); + + if (pattern.size() > 0 && intensities.size() > 0) { + vibration.vibrate(pattern, repeat, intensities); + } else if (pattern.size() > 0) { + vibration.vibrate(pattern, repeat); + } else { + vibration.vibrate(duration, amplitude); + } + + result.success(null); + + break; + case "cancel": + vibration.getVibrator().cancel(); + + result.success(null); + + break; + default: + result.notImplemented(); + } + } +} \ No newline at end of file diff --git a/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/VibrationPlugin.java b/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/VibrationPlugin.java new file mode 100644 index 000000000..5c8a50dd4 --- /dev/null +++ b/third_party/pub_patches/vibration/android/src/main/java/com/benjaminabel/vibration/VibrationPlugin.java @@ -0,0 +1,36 @@ +package com.benjaminabel.vibration; + +import android.content.Context; +import android.os.Vibrator; + +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodChannel; + +public class VibrationPlugin implements FlutterPlugin { + private static final String CHANNEL = "vibration"; + private MethodChannel methodChannel; + + @Override + public void onDetachedFromEngine(FlutterPluginBinding binding) { + teardownChannels(); + } + + @Override + public void onAttachedToEngine(FlutterPluginBinding binding) { + setupChannels(binding.getBinaryMessenger(), binding.getApplicationContext()); + } + + private void setupChannels(BinaryMessenger messenger, Context context) { + final Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + final VibrationMethodChannelHandler methodChannelHandler = new VibrationMethodChannelHandler(new Vibration(vibrator)); + + this.methodChannel = new MethodChannel(messenger, CHANNEL); + this.methodChannel.setMethodCallHandler(methodChannelHandler); + } + + private void teardownChannels() { + this.methodChannel.setMethodCallHandler(null); + this.methodChannel = null; + } +} diff --git a/third_party/pub_patches/vibration/example/README.md b/third_party/pub_patches/vibration/example/README.md new file mode 100644 index 000000000..b2d98fee2 --- /dev/null +++ b/third_party/pub_patches/vibration/example/README.md @@ -0,0 +1,16 @@ +# Vibration Example + +Demonstrates how to use the vibration plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.io/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/third_party/pub_patches/vibration/example/android/app/build.gradle b/third_party/pub_patches/vibration/example/android/app/build.gradle new file mode 100644 index 000000000..040cb6631 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/app/build.gradle @@ -0,0 +1,62 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + namespace 'com.benjaminabel.vibration_example' + compileSdkVersion 33 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.benjaminabel.vibration_example" + minSdkVersion 19 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/third_party/pub_patches/vibration/example/android/app/src/debug/AndroidManifest.xml b/third_party/pub_patches/vibration/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..8d85bb626 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/AndroidManifest.xml b/third_party/pub_patches/vibration/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..601c02dd2 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/java/com/benjaminabel/vibrationexample/MainActivity.java b/third_party/pub_patches/vibration/example/android/app/src/main/java/com/benjaminabel/vibrationexample/MainActivity.java new file mode 100644 index 000000000..04550778e --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/app/src/main/java/com/benjaminabel/vibrationexample/MainActivity.java @@ -0,0 +1,5 @@ +package com.benjaminabel.vibration_example; + +import io.flutter.embedding.android.FlutterActivity; + +public class MainActivity extends FlutterActivity { } diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/res/drawable/launch_background.xml b/third_party/pub_patches/vibration/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..db77bb4b7 Binary files /dev/null and b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..17987b79b Binary files /dev/null and b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09d439148 Binary files /dev/null and b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5f1c8d34 Binary files /dev/null and b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4d6372eeb Binary files /dev/null and b/third_party/pub_patches/vibration/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/third_party/pub_patches/vibration/example/android/app/src/main/res/values/styles.xml b/third_party/pub_patches/vibration/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..00fa4417c --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/third_party/pub_patches/vibration/example/android/app/src/profile/AndroidManifest.xml b/third_party/pub_patches/vibration/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..8d85bb626 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/third_party/pub_patches/vibration/example/android/build.gradle b/third_party/pub_patches/vibration/example/android/build.gradle new file mode 100644 index 000000000..7df2e8e3a --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.4.0' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/third_party/pub_patches/vibration/example/android/gradle.properties b/third_party/pub_patches/vibration/example/android/gradle.properties new file mode 100644 index 000000000..b6e61b62b --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/gradle.properties @@ -0,0 +1,4 @@ +android.enableJetifier=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true diff --git a/third_party/pub_patches/vibration/example/android/gradle/wrapper/gradle-wrapper.properties b/third_party/pub_patches/vibration/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..c8e218c58 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Oct 04 11:09:11 EEST 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/third_party/pub_patches/vibration/example/android/settings.gradle b/third_party/pub_patches/vibration/example/android/settings.gradle new file mode 100644 index 000000000..5a2f14fb1 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/third_party/pub_patches/vibration/example/android/settings_aar.gradle b/third_party/pub_patches/vibration/example/android/settings_aar.gradle new file mode 100644 index 000000000..e7b4def49 --- /dev/null +++ b/third_party/pub_patches/vibration/example/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/third_party/pub_patches/vibration/example/ios/Flutter/AppFrameworkInfo.plist b/third_party/pub_patches/vibration/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..9367d483e --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/third_party/pub_patches/vibration/example/ios/Flutter/Debug.xcconfig b/third_party/pub_patches/vibration/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..e8efba114 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/vibration/example/ios/Flutter/Flutter.podspec b/third_party/pub_patches/vibration/example/ios/Flutter/Flutter.podspec new file mode 100644 index 000000000..5ca30416b --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.description = <<-DESC +Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. + DESC + s.homepage = 'https://flutter.io' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '8.0' + s.vendored_frameworks = 'Flutter.framework' +end diff --git a/third_party/pub_patches/vibration/example/ios/Flutter/Release.xcconfig b/third_party/pub_patches/vibration/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..399e9340e --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/third_party/pub_patches/vibration/example/ios/Podfile b/third_party/pub_patches/vibration/example/ios/Podfile new file mode 100644 index 000000000..6697f0a53 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Podfile @@ -0,0 +1,87 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + generated_key_values = {} + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end + end + generated_key_values +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Flutter Pod + + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' + + # Plugin Pods + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/project.pbxproj b/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..c94fae473 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,582 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + B81A092DAD7C383A0DCE647C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DBF91C0450FEBD606F79F293 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4AB533FF1EC44E65CA666EBE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 6535C1EDEB2F6571647C6337 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7EBDC7375CF5807894BEE684 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DBF91C0450FEBD606F79F293 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B81A092DAD7C383A0DCE647C /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 94D0DF38F0B5CF1E98CA27CA /* Frameworks */ = { + isa = PBXGroup; + children = ( + DBF91C0450FEBD606F79F293 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + CD50584B0FE01EEE5D11019F /* Pods */, + 94D0DF38F0B5CF1E98CA27CA /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + CD50584B0FE01EEE5D11019F /* Pods */ = { + isa = PBXGroup; + children = ( + 4AB533FF1EC44E65CA666EBE /* Pods-Runner.debug.xcconfig */, + 6535C1EDEB2F6571647C6337 /* Pods-Runner.release.xcconfig */, + 7EBDC7375CF5807894BEE684 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 8234DECF475B2EA0497A2934 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + F88E023FBC98CCFF492ADB21 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1220; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0910; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 8234DECF475B2EA0497A2934 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + F88E023FBC98CCFF492ADB21 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/vibration/vibration.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/vibration.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = S8QB4VV633; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.benjaminabel.vibrationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.benjaminabel.vibrationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.benjaminabel.vibrationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..1d526a16e --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..87c278dbd --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/vibration/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/third_party/pub_patches/vibration/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/third_party/pub_patches/vibration/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/pub_patches/vibration/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/third_party/pub_patches/vibration/example/ios/Runner/AppDelegate.swift b/third_party/pub_patches/vibration/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..70693e4a8 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 000000000..3d43d11e6 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 000000000..28c6bf030 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 000000000..f091b6b0b Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 000000000..4cde12118 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 000000000..d0ef06e7e Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 000000000..dcdc2306c Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 000000000..2ccbfd967 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 000000000..c8f9ed8f5 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 000000000..a6d6b8609 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 000000000..75b2d164a Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 000000000..c4df70d39 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 000000000..6a84f41e1 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 000000000..d0e1f5853 Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000..0bedcf2fd --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 000000000..9da19eaca Binary files /dev/null and b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/third_party/pub_patches/vibration/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Base.lproj/Main.storyboard b/third_party/pub_patches/vibration/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..14cc81a36 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Info.plist b/third_party/pub_patches/vibration/example/ios/Runner/Info.plist new file mode 100644 index 000000000..00fb91182 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + vibration_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/third_party/pub_patches/vibration/example/ios/Runner/Runner-Bridging-Header.h b/third_party/pub_patches/vibration/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..7335fdf90 --- /dev/null +++ b/third_party/pub_patches/vibration/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/third_party/pub_patches/vibration/example/lib/main.dart b/third_party/pub_patches/vibration/example/lib/main.dart new file mode 100644 index 000000000..81e37fdbb --- /dev/null +++ b/third_party/pub_patches/vibration/example/lib/main.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:vibration/vibration.dart'; + +void main() => runApp(VibratingApp()); + +class VibratingApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Vibration Plugin example app'), + ), + body: Builder( + builder: (BuildContext context) { + return Center( + child: Column( + children: [ + ElevatedButton( + child: Text('Vibrate for default 500ms'), + onPressed: () { + Vibration.vibrate(); + }, + ), + ElevatedButton( + child: Text('Vibrate for 1000ms'), + onPressed: () { + Vibration.vibrate(duration: 1000); + }, + ), + ElevatedButton( + child: Text('Vibrate with pattern'), + onPressed: () { + final snackBar = SnackBar( + content: Text( + 'Pattern: wait 0.5s, vibrate 1s, wait 0.5s, vibrate 2s, wait 0.5s, vibrate 3s, wait 0.5s, vibrate 0.5s', + ), + ); + ScaffoldMessenger.of(context).showSnackBar(snackBar); + Vibration.vibrate( + pattern: [500, 1000, 500, 2000, 500, 3000, 500, 500], + ); + }, + ), + ElevatedButton( + child: Text('Vibrate with pattern and amplitude'), + onPressed: () { + final snackBar = SnackBar( + content: Text( + 'Pattern: wait 0.5s, vibrate 1s, wait 0.5s, vibrate 2s, wait 0.5s, vibrate 3s, wait 0.5s, vibrate 0.5s', + ), + ); + + ScaffoldMessenger.of(context).showSnackBar(snackBar); + Vibration.vibrate( + pattern: [500, 1000, 500, 2000, 500, 3000, 500, 500], + intensities: [0, 128, 0, 255, 0, 64, 0, 255], + ); + }, + ) + ], + ), + ); + }, + ), + ), + ); + } +} diff --git a/third_party/pub_patches/vibration/example/pubspec.yaml b/third_party/pub_patches/vibration/example/pubspec.yaml new file mode 100644 index 000000000..ae737df98 --- /dev/null +++ b/third_party/pub_patches/vibration/example/pubspec.yaml @@ -0,0 +1,64 @@ +name: vibration_example +description: Demonstrates how to use the vibration plugin. +publish_to: "none" +version: 1.0.0 + +environment: + sdk: ">=2.12.1 <4.0.0" + +dependencies: + flutter: + sdk: flutter + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.0 + vibration: + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + + + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.io/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.io/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.io/custom-fonts/#from-packages diff --git a/third_party/pub_patches/vibration/example/test/widget_test.dart b/third_party/pub_patches/vibration/example/test/widget_test.dart new file mode 100644 index 000000000..6fd95158f --- /dev/null +++ b/third_party/pub_patches/vibration/example/test/widget_test.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import '../lib/main.dart'; + +void main() { + testWidgets( + 'Buttons rendered', + (WidgetTester tester) async { + await tester.pumpWidget(VibratingApp()); + + expect( + find.byWidgetPredicate( + (Widget widget) => widget is ElevatedButton, + ), + findsNWidgets(3), + ); + }, + ); +} diff --git a/third_party/pub_patches/vibration/example/web/favicon.png b/third_party/pub_patches/vibration/example/web/favicon.png new file mode 100644 index 000000000..8aaa46ac1 Binary files /dev/null and b/third_party/pub_patches/vibration/example/web/favicon.png differ diff --git a/third_party/pub_patches/vibration/example/web/icons/Icon-192.png b/third_party/pub_patches/vibration/example/web/icons/Icon-192.png new file mode 100644 index 000000000..b749bfef0 Binary files /dev/null and b/third_party/pub_patches/vibration/example/web/icons/Icon-192.png differ diff --git a/third_party/pub_patches/vibration/example/web/icons/Icon-512.png b/third_party/pub_patches/vibration/example/web/icons/Icon-512.png new file mode 100644 index 000000000..88cfd48df Binary files /dev/null and b/third_party/pub_patches/vibration/example/web/icons/Icon-512.png differ diff --git a/third_party/pub_patches/vibration/example/web/index.html b/third_party/pub_patches/vibration/example/web/index.html new file mode 100644 index 000000000..a0c14606f --- /dev/null +++ b/third_party/pub_patches/vibration/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/third_party/pub_patches/vibration/example/web/manifest.json b/third_party/pub_patches/vibration/example/web/manifest.json new file mode 100644 index 000000000..8c012917d --- /dev/null +++ b/third_party/pub_patches/vibration/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/third_party/pub_patches/vibration/ios/Classes/VibrationPlugin.h b/third_party/pub_patches/vibration/ios/Classes/VibrationPlugin.h new file mode 100644 index 000000000..f8e6e428c --- /dev/null +++ b/third_party/pub_patches/vibration/ios/Classes/VibrationPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface VibrationPlugin : NSObject +@end diff --git a/third_party/pub_patches/vibration/ios/Classes/VibrationPlugin.m b/third_party/pub_patches/vibration/ios/Classes/VibrationPlugin.m new file mode 100644 index 000000000..97412456e --- /dev/null +++ b/third_party/pub_patches/vibration/ios/Classes/VibrationPlugin.m @@ -0,0 +1,12 @@ +#import "VibrationPlugin.h" +#if __has_include() +#import +#else +#import "vibration-Swift.h" +#endif + +@implementation VibrationPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [VibrationPluginSwift registerWithRegistrar:registrar]; +} +@end diff --git a/third_party/pub_patches/vibration/ios/Classes/VibrationPluginSwift.swift b/third_party/pub_patches/vibration/ios/Classes/VibrationPluginSwift.swift new file mode 100644 index 000000000..260778014 --- /dev/null +++ b/third_party/pub_patches/vibration/ios/Classes/VibrationPluginSwift.swift @@ -0,0 +1,180 @@ +import AudioToolbox +import CoreHaptics +import Flutter +import UIKit + +public class VibrationPluginSwift: NSObject, FlutterPlugin { +#if targetEnvironment(simulator) + private let isDevice = false +#else + private let isDevice = true +#endif + + @available(iOS 13.0, *) + public static var engine: CHHapticEngine? + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "vibration", binaryMessenger: registrar.messenger()) + let instance = VibrationPluginSwift() + + if #available(iOS 13.0, *) { + VibrationPluginSwift.createEngine() + } + + registrar.addMethodCallDelegate(instance, channel: channel) + } + + @available(iOS 13.0, *) + public static func createEngine() { + // Create and configure a haptic engine. + do { + VibrationPluginSwift.engine = try CHHapticEngine() + } catch { + print("Engine creation error: \(error)") + return + } + + if VibrationPluginSwift.engine == nil { + print("Failed to create engine!") + } + + // The stopped handler alerts you of engine stoppage due to external causes. + VibrationPluginSwift.engine?.stoppedHandler = { reason in + print("The engine stopped for reason: \(reason.rawValue)") + } + + // The reset handler provides an opportunity for your app to restart the engine in case of failure. + VibrationPluginSwift.engine?.resetHandler = { + // Try restarting the engine. + print("The engine reset --> Restarting now!") + + do { + try VibrationPluginSwift.engine?.start() + } catch { + print("Failed to restart the engine: \(error)") + } + } + } + + private func supportsHaptics() -> Bool { + if #available(iOS 13.0, *) { + return CHHapticEngine.capabilitiesForHardware().supportsHaptics + } + + return false; + } + + @available(iOS 13.0, *) + private func playPattern(myArgs: [String: Any], pattern: [Int]) -> Void { + // Get event parameters, if any + var params: [CHHapticEventParameter] = [] + //var amplitudes: [Int] = [] + let amplitudes = myArgs["intensities"] as! [Int] + + // Create haptic events + var hapticEvents: [CHHapticEvent] = [] + var i: Int = 0 + var rel: Double = 0.0 + + while i < pattern.count { + // Get intensity parameter, if any + if (i < amplitudes.count) { + if(amplitudes[i] != 0) { + let p = CHHapticEventParameter(parameterID: .hapticIntensity, value: Float(Double(amplitudes[i]) / 255.0)) + // Get wait time and duration + let duration = Double(pattern[i]) / 1000.0 + // Create haptic event + let e = CHHapticEvent( + eventType: .hapticContinuous, + parameters: [p], + relativeTime: rel, + duration: duration + ) + hapticEvents.append(e) + // Add duration to relative time + rel += duration + } + else { + let waitTime = Double(pattern[i]) / 1000.0 + rel += waitTime + } + } + i += 1 + } + // Try to play engine + do { + if let engine = VibrationPluginSwift.engine { + let patternToPlay = try CHHapticPattern(events: hapticEvents, parameters: []) + let player = try engine.makePlayer(with: patternToPlay) + try engine.start() + try player.start(atTime: 0) + } + } catch { + print("Failed to play pattern: \(error.localizedDescription).") + } + } + @available(iOS 13.0, *) + private func cancelVibration() { + VibrationPluginSwift.engine?.stop(completionHandler: { error in + if let error = error { + print("Error stopping haptic engine: \(error)") + } else { + print("Haptic engine stopped successfully.") + } + }) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "hasCustomVibrationsSupport": + result(supportsHaptics()) + case "vibrate": + guard let args = call.arguments else { + result(false) + return + } + + guard let myArgs = args as? [String: Any] else { + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate) + result(true) + return + } + + guard let pattern = myArgs["pattern"] as? [Int] else { + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate) + result(true) + return + } + + if pattern.count == 0 { + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate) + result(true) + return + } + + assert(pattern.count % 2 == 0, "Pattern must have even number of elements!") + + if !supportsHaptics() { + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate) + result(true) + return + } + + if #available(iOS 13.0, *) { + playPattern(myArgs: myArgs, pattern: pattern) + } + + result(isDevice) + case "cancel": + if #available(iOS 13.0, *) { + cancelVibration() + } else { + result(false) + } + result(true) + return + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/third_party/pub_patches/vibration/ios/vibration.podspec b/third_party/pub_patches/vibration/ios/vibration.podspec new file mode 100644 index 000000000..994bc23a2 --- /dev/null +++ b/third_party/pub_patches/vibration/ios/vibration.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'vibration' + s.version = '1.7.5' + s.summary = 'A plugin for handling Vibration API on iOS and Android devices' + s.description = <<-DESC +Handle vibration on iOS and Android + DESC + s.homepage = 'https://github.com/benjamindean/flutter_vibration' + s.license = { :file => '../LICENSE' } + s.author = { 'Benjamin Dean' => 'benjaminabel.cellardoor@gmail.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.platform = :ios, '8.0' + + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } + s.swift_version = '5.3' +end diff --git a/third_party/pub_patches/vibration/lib/vibration.dart b/third_party/pub_patches/vibration/lib/vibration.dart new file mode 100644 index 000000000..b8150beed --- /dev/null +++ b/third_party/pub_patches/vibration/lib/vibration.dart @@ -0,0 +1,88 @@ +library vibration; + +import 'dart:async'; + +import 'package:vibration_platform_interface/vibration_platform_interface.dart'; +export 'package:vibration_platform_interface/vibration_platform_interface.dart'; + +/// Platform-independent vibration methods. +class Vibration { + /// Check if vibrator is available on device. + /// + /// ```dart + /// if (await Vibration.hasVibrator()) { + /// Vibration.vibrate(); + /// } + /// ``` + static Future hasVibrator() async { + return VibrationPlatform.instance.hasVibrator(); + } + + /// Check if the vibrator has amplitude control. + /// + /// ```dart + /// if (await Vibration.hasAmplitudeControl()) { + /// Vibration.vibrate(amplitude: 128); + /// } + /// ``` + static Future hasAmplitudeControl() async { + return VibrationPlatform.instance.hasAmplitudeControl(); + } + + /// Check if the device is able to vibrate with a custom + /// [duration], [pattern] or [intensities]. + /// May return `true` even if the device has no vibrator. + /// + /// ```dart + /// if (await Vibration.hasCustomVibrationsSupport()) { + /// Vibration.vibrate(duration: 1000); + /// } else { + /// Vibration.vibrate(); + /// await Future.delayed(Duration(milliseconds: 500)); + /// Vibration.vibrate(); + /// } + /// ``` + static Future hasCustomVibrationsSupport() async { + return VibrationPlatform.instance.hasCustomVibrationsSupport(); + } + + /// Vibrate with [duration] at [amplitude] or [pattern] at [intensities]. + /// + /// The default vibration duration is 500ms. + /// Amplitude is a range from 1 to 255, if supported. + /// + /// ```dart + /// Vibration.vibrate(duration: 1000); + /// + /// if (await Vibration.hasAmplitudeControl()) { + /// Vibration.vibrate(duration: 1000, amplitude: 1); + /// Vibration.vibrate(duration: 1000, amplitude: 255); + /// } + /// ``` + static Future vibrate({ + int duration = 500, + List pattern = const [], + int repeat = -1, + List intensities = const [], + int amplitude = -1, + }) { + return VibrationPlatform.instance.vibrate( + duration: duration, + pattern: pattern, + repeat: repeat, + intensities: intensities, + amplitude: amplitude, + ); + } + + /// This method is used to cancel an ongoing vibration. + /// iOS: only works for custom haptic vibrations using `CHHapticEngine. + /// + /// ```dart + /// Vibration.vibrate(duration: 10000); + /// Vibration.cancel(); + /// ``` + static Future cancel() { + return VibrationPlatform.instance.cancel(); + } +} diff --git a/third_party/pub_patches/vibration/pubspec.yaml b/third_party/pub_patches/vibration/pubspec.yaml new file mode 100644 index 000000000..a60b1ad1b --- /dev/null +++ b/third_party/pub_patches/vibration/pubspec.yaml @@ -0,0 +1,33 @@ +name: vibration +description: A plugin for handling Vibration API on iOS, Android, web and OpenHarmony. +version: 1.9.0 +homepage: https://github.com/benjamindean/flutter_vibration + +environment: + sdk: ">=2.12.1 <4.0.0" + flutter: ">=1.20.0" + +dependencies: + flutter: + sdk: flutter + # TODO: Change pub.dev's version when vibration_web is published + # vibration_web: ^1.6.6 + vibration_platform_interface: ^0.0.1 + +# dependency_overrides: +# vibration_platform_interface: +# path: ../vibration_platform_interface +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + plugin: + platforms: + android: + package: com.benjaminabel.vibration + pluginClass: VibrationPlugin + ios: + pluginClass: VibrationPlugin + # web: + # default_package: vibration_web \ No newline at end of file diff --git a/third_party/pub_patches/vibration/test/vibration_test.dart b/third_party/pub_patches/vibration/test/vibration_test.dart new file mode 100644 index 000000000..3130b1fca --- /dev/null +++ b/third_party/pub_patches/vibration/test/vibration_test.dart @@ -0,0 +1,148 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:vibration/vibration.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + const MethodChannel channel = MethodChannel('vibration'); + final List log = []; + + setUp(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) { + log.add(methodCall); + + return null; + }); + }); + + tearDown(() { + log.clear(); + }); + + group('hasVibrator', () { + test( + 'returns false', + () async { + bool? hasVibrator = await Vibration.hasVibrator(); + + expect( + hasVibrator, + equals(false), + ); + }, + ); + + test('throws PlatformException', () async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + throw PlatformException(code: 'error'); + }); + + final hasVibrator = await Vibration.hasVibrator(); + + throwsA(isA()); + expect(hasVibrator, isFalse); + }); + + test('throws UnsupportedError', () async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + throw UnsupportedError('error'); + }); + + final hasVibrator = await Vibration.hasVibrator(); + + throwsA(isA()); + expect(hasVibrator, isFalse); + }); + }); + + group('hasAmplitudeControl', () { + test( + 'returns false', + () async { + bool? hasAmplitudeControl = await Vibration.hasAmplitudeControl(); + + expect(hasAmplitudeControl, isFalse); + }, + ); + + test('throws PlatformException', () async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + throw PlatformException(code: 'error'); + }); + + final hasAmplitudeControl = await Vibration.hasAmplitudeControl(); + + throwsA(isA()); + expect(hasAmplitudeControl, isFalse); + }); + + test('throws UnsupportedError', () async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + throw UnsupportedError('error'); + }); + + final hasAmplitudeControl = await Vibration.hasAmplitudeControl(); + + throwsA(isA()); + expect(hasAmplitudeControl, isFalse); + }); + }); + + test( + 'vibrate with duration', + () async { + await Vibration.vibrate(duration: 100); + + expect( + log, + [ + isMethodCall('vibrate', arguments: { + 'duration': 100, + 'pattern': [], + 'repeat': -1, + 'amplitude': -1, + 'intensities': [] + }) + ], + ); + }, + ); + + test( + 'vibrate with pattern', + () async { + await Vibration.vibrate(pattern: [100, 200, 400], repeat: 1); + + expect( + log, + [ + isMethodCall('vibrate', arguments: { + 'duration': 500, + 'pattern': [100, 200, 400], + 'repeat': 1, + 'amplitude': -1, + 'intensities': [] + }) + ], + ); + }, + ); + + test( + 'cancel vibration', + () async { + await Vibration.cancel(); + + expect( + log, + [isMethodCall('cancel', arguments: null)], + ); + }, + ); +}