feat: add PiP error notifications

This commit is contained in:
edde746
2026-01-21 23:58:16 +01:00
parent 19049365cc
commit fb9105f84e
21 changed files with 343 additions and 40 deletions
@@ -2,7 +2,9 @@ package com.edde746.plezy
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.app.AppOpsManager
import android.app.PictureInPictureParams import android.app.PictureInPictureParams
import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import android.util.Rational import android.util.Rational
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
@@ -34,13 +36,41 @@ class MainActivity : FlutterActivity() {
result.success(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) result.success(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
} }
"enter" -> { "enter" -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
result.success(mapOf("success" to false, "errorCode" to "android_version"))
return@setMethodCallHandler
}
// Check if PiP permission is granted via AppOpsManager
val appOpsManager = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
val pipAllowed = appOpsManager.checkOpNoThrow(
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
applicationInfo.uid,
packageName
) == AppOpsManager.MODE_ALLOWED
if (!pipAllowed) {
result.success(mapOf("success" to false, "errorCode" to "permission_disabled"))
return@setMethodCallHandler
}
try {
val width = call.argument<Int>("width") ?: 16 val width = call.argument<Int>("width") ?: 16
val height = call.argument<Int>("height") ?: 9 val height = call.argument<Int>("height") ?: 9
val params = PictureInPictureParams.Builder().setAspectRatio(Rational(width, height)).build() val params = PictureInPictureParams.Builder()
enterPictureInPictureMode(params) .setAspectRatio(Rational(width, height))
.build()
val success = enterPictureInPictureMode(params)
if (success) {
result.success(mapOf("success" to true))
} else {
result.success(mapOf("success" to false, "errorCode" to "failed"))
}
} catch (e: IllegalStateException) {
result.success(mapOf("success" to false, "errorCode" to "not_supported"))
} catch (e: Exception) {
result.success(mapOf("success" to false, "errorCode" to "unknown", "errorMessage" to (e.message ?: "Unknown error")))
} }
result.success(null)
} else -> result.notImplemented() } else -> result.notImplemented()
} }
} }
+9 -1
View File
@@ -290,7 +290,15 @@
"rotationLockButton": "Dreh­sperre", "rotationLockButton": "Dreh­sperre",
"timelineSlider": "Video-Zeitleiste", "timelineSlider": "Video-Zeitleiste",
"volumeSlider": "Lautstärkepegel", "volumeSlider": "Lautstärkepegel",
"backButton": "Zurück" "backButton": "Zurück",
"pipFailed": "Bild-in-Bild konnte nicht gestartet werden",
"pipErrors": {
"androidVersion": "Erfordert Android 8.0 oder neuer",
"permissionDisabled": "Bild-in-Bild-Berechtigung ist deaktiviert. Aktiviere sie unter Einstellungen > Apps > Plezy > Bild-in-Bild",
"notSupported": "Dieses Gerät unterstützt den Bild-in-Bild-Modus nicht",
"failed": "Bild-in-Bild konnte nicht gestartet werden",
"unknown": "Ein Fehler ist aufgetreten: ${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "Eigentümer", "admin": "Eigentümer",
+9 -1
View File
@@ -289,7 +289,15 @@
"rotationLockButton": "Rotation lock", "rotationLockButton": "Rotation lock",
"timelineSlider": "Video timeline", "timelineSlider": "Video timeline",
"volumeSlider": "Volume level", "volumeSlider": "Volume level",
"backButton": "Back" "backButton": "Back",
"pipFailed": "Picture-in-picture failed to start",
"pipErrors": {
"androidVersion": "Requires Android 8.0 or newer",
"permissionDisabled": "Picture-in-picture permission is disabled. Enable it in Settings > Apps > Plezy > Picture-in-picture",
"notSupported": "Device doesn't support picture-in-picture mode",
"failed": "Picture-in-picture failed to start",
"unknown": "An error occurred: ${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "Admin", "admin": "Admin",
+9 -1
View File
@@ -289,7 +289,15 @@
"rotationLockButton": "Verrouillage de rotation", "rotationLockButton": "Verrouillage de rotation",
"timelineSlider": "Timeline vidéo", "timelineSlider": "Timeline vidéo",
"volumeSlider": "Niveau sonore", "volumeSlider": "Niveau sonore",
"backButton": "Retour" "backButton": "Retour",
"pipFailed": "Échec du démarrage du mode image dans l'image",
"pipErrors": {
"androidVersion": "Nécessite Android 8.0 ou plus récent",
"permissionDisabled": "L'autorisation Image dans l'image est désactivée. Activez-la dans Paramètres > Applications > Plezy > Image dans l'image",
"notSupported": "Cet appareil ne prend pas en charge le mode image dans l'image",
"failed": "Échec du démarrage du mode image dans l'image",
"unknown": "Une erreur s'est produite : ${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "Admin", "admin": "Admin",
+9 -1
View File
@@ -290,7 +290,15 @@
"rotationLockButton": "Blocco rotazione", "rotationLockButton": "Blocco rotazione",
"timelineSlider": "Timeline video", "timelineSlider": "Timeline video",
"volumeSlider": "Livello volume", "volumeSlider": "Livello volume",
"backButton": "Indietro" "backButton": "Indietro",
"pipFailed": "Impossibile avviare la modalità Picture-in-Picture",
"pipErrors": {
"androidVersion": "Richiede Android 8.0 o versioni successive",
"permissionDisabled": "L'autorizzazione Picture-in-Picture è disabilitata. Abilitala in Impostazioni > App > Plezy > Picture-in-Picture",
"notSupported": "Questo dispositivo non supporta la modalità Picture-in-Picture",
"failed": "Impossibile avviare la modalità Picture-in-Picture",
"unknown": "Si è verificato un errore: ${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "Admin", "admin": "Admin",
+9 -1
View File
@@ -290,7 +290,15 @@
"rotationLockButton": "회전 잠금", "rotationLockButton": "회전 잠금",
"timelineSlider": "타임라인", "timelineSlider": "타임라인",
"volumeSlider": "볼륨 조절", "volumeSlider": "볼륨 조절",
"backButton": "뒤로 가기" "backButton": "뒤로 가기",
"pipFailed": "화면 속 화면 모드를 시작할 수 없습니다",
"pipErrors": {
"androidVersion": "Android 8.0 이상이 필요합니다",
"permissionDisabled": "화면 속 화면 권한이 비활성화되어 있습니다. 설정 > 앱 > Plezy > 화면 속 화면에서 활성화하세요",
"notSupported": "이 기기는 화면 속 화면 모드를 지원하지 않습니다",
"failed": "화면 속 화면 모드를 시작할 수 없습니다",
"unknown": "오류가 발생했습니다: ${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "관리자", "admin": "관리자",
+9 -1
View File
@@ -290,7 +290,15 @@
"rotationLockButton": "Rotatievergrendeling", "rotationLockButton": "Rotatievergrendeling",
"timelineSlider": "Videotijdlijn", "timelineSlider": "Videotijdlijn",
"volumeSlider": "Volumeniveau", "volumeSlider": "Volumeniveau",
"backButton": "Terug" "backButton": "Terug",
"pipFailed": "Beeld-in-beeld kon niet worden gestart",
"pipErrors": {
"androidVersion": "Vereist Android 8.0 of nieuwer",
"permissionDisabled": "Beeld-in-beeld toestemming is uitgeschakeld. Schakel deze in via Instellingen > Apps > Plezy > Beeld-in-beeld",
"notSupported": "Dit apparaat ondersteunt geen beeld-in-beeld modus",
"failed": "Beeld-in-beeld kon niet worden gestart",
"unknown": "Er is een fout opgetreden: ${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "Beheerder", "admin": "Beheerder",
+2 -2
View File
@@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang` /// To regenerate, run: `dart run slang`
/// ///
/// Locales: 8 /// Locales: 8
/// Strings: 4324 (540 per locale) /// Strings: 4372 (546 per locale)
/// ///
/// Built on 2026-01-20 at 15:18 UTC /// Built on 2026-01-21 at 22:57 UTC
// coverage:ignore-file // coverage:ignore-file
// ignore_for_file: type=lint, unused_import // ignore_for_file: type=lint, unused_import
+24 -2
View File
@@ -442,6 +442,8 @@ class _TranslationsVideoControlsDe implements TranslationsVideoControlsEn {
@override String get timelineSlider => 'Video-Zeitleiste'; @override String get timelineSlider => 'Video-Zeitleiste';
@override String get volumeSlider => 'Lautstärkepegel'; @override String get volumeSlider => 'Lautstärkepegel';
@override String get backButton => 'Zurück'; @override String get backButton => 'Zurück';
@override String get pipFailed => 'Bild-in-Bild konnte nicht gestartet werden';
@override late final _TranslationsVideoControlsPipErrorsDe pipErrors = _TranslationsVideoControlsPipErrorsDe._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -902,6 +904,20 @@ class _TranslationsHotkeysActionsDe implements TranslationsHotkeysActionsEn {
@override String get subSeekPrev => 'Zum vorherigen Untertitel springen'; @override String get subSeekPrev => 'Zum vorherigen Untertitel springen';
} }
// Path: videoControls.pipErrors
class _TranslationsVideoControlsPipErrorsDe implements TranslationsVideoControlsPipErrorsEn {
_TranslationsVideoControlsPipErrorsDe._(this._root);
final TranslationsDe _root; // ignore: unused_field
// Translations
@override String get androidVersion => 'Erfordert Android 8.0 oder neuer';
@override String get permissionDisabled => 'Bild-in-Bild-Berechtigung ist deaktiviert. Aktiviere sie unter Einstellungen > Apps > Plezy > Bild-in-Bild';
@override String get notSupported => 'Dieses Gerät unterstützt den Bild-in-Bild-Modus nicht';
@override String get failed => 'Bild-in-Bild konnte nicht gestartet werden';
@override String unknown({required Object error}) => 'Ein Fehler ist aufgetreten: ${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class _TranslationsLibrariesTabsDe implements TranslationsLibrariesTabsEn { class _TranslationsLibrariesTabsDe implements TranslationsLibrariesTabsEn {
_TranslationsLibrariesTabsDe._(this._root); _TranslationsLibrariesTabsDe._(this._root);
@@ -1201,6 +1217,12 @@ extension on TranslationsDe {
'videoControls.timelineSlider' => 'Video-Zeitleiste', 'videoControls.timelineSlider' => 'Video-Zeitleiste',
'videoControls.volumeSlider' => 'Lautstärkepegel', 'videoControls.volumeSlider' => 'Lautstärkepegel',
'videoControls.backButton' => 'Zurück', 'videoControls.backButton' => 'Zurück',
'videoControls.pipFailed' => 'Bild-in-Bild konnte nicht gestartet werden',
'videoControls.pipErrors.androidVersion' => 'Erfordert Android 8.0 oder neuer',
'videoControls.pipErrors.permissionDisabled' => 'Bild-in-Bild-Berechtigung ist deaktiviert. Aktiviere sie unter Einstellungen > Apps > Plezy > Bild-in-Bild',
'videoControls.pipErrors.notSupported' => 'Dieses Gerät unterstützt den Bild-in-Bild-Modus nicht',
'videoControls.pipErrors.failed' => 'Bild-in-Bild konnte nicht gestartet werden',
'videoControls.pipErrors.unknown' => ({required Object error}) => 'Ein Fehler ist aufgetreten: ${error}',
'userStatus.admin' => 'Eigentümer', 'userStatus.admin' => 'Eigentümer',
'userStatus.restricted' => 'Eingeschränkt', 'userStatus.restricted' => 'Eingeschränkt',
'userStatus.protected' => 'Geschützt', 'userStatus.protected' => 'Geschützt',
@@ -1444,14 +1466,14 @@ extension on TranslationsDe {
'watchTogether.joining' => 'Beitreten...', 'watchTogether.joining' => 'Beitreten...',
'watchTogether.controlMode' => 'Steuerungsmodus', 'watchTogether.controlMode' => 'Steuerungsmodus',
'watchTogether.controlModeQuestion' => 'Wer kann die Wiedergabe steuern?', 'watchTogether.controlModeQuestion' => 'Wer kann die Wiedergabe steuern?',
_ => null,
} ?? switch (path) {
'watchTogether.hostOnly' => 'Nur Host', 'watchTogether.hostOnly' => 'Nur Host',
'watchTogether.anyone' => 'Alle', 'watchTogether.anyone' => 'Alle',
'watchTogether.hostingSession' => 'Sitzung Hosten', 'watchTogether.hostingSession' => 'Sitzung Hosten',
'watchTogether.inSession' => 'In Sitzung', 'watchTogether.inSession' => 'In Sitzung',
'watchTogether.sessionCode' => 'Sitzungscode', 'watchTogether.sessionCode' => 'Sitzungscode',
'watchTogether.hostControlsPlayback' => 'Host steuert die Wiedergabe', 'watchTogether.hostControlsPlayback' => 'Host steuert die Wiedergabe',
_ => null,
} ?? switch (path) {
'watchTogether.anyoneCanControl' => 'Alle können die Wiedergabe steuern', 'watchTogether.anyoneCanControl' => 'Alle können die Wiedergabe steuern',
'watchTogether.hostControls' => 'Host steuert', 'watchTogether.hostControls' => 'Host steuert',
'watchTogether.anyoneControls' => 'Alle steuern', 'watchTogether.anyoneControls' => 'Alle steuern',
+37 -2
View File
@@ -935,6 +935,11 @@ class TranslationsVideoControlsEn {
/// en: 'Back' /// en: 'Back'
String get backButton => 'Back'; String get backButton => 'Back';
/// en: 'Picture-in-picture failed to start'
String get pipFailed => 'Picture-in-picture failed to start';
late final TranslationsVideoControlsPipErrorsEn pipErrors = TranslationsVideoControlsPipErrorsEn._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -1963,6 +1968,30 @@ class TranslationsHotkeysActionsEn {
String get subSeekPrev => 'Seek to Previous Subtitle'; String get subSeekPrev => 'Seek to Previous Subtitle';
} }
// Path: videoControls.pipErrors
class TranslationsVideoControlsPipErrorsEn {
TranslationsVideoControlsPipErrorsEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
/// en: 'Requires Android 8.0 or newer'
String get androidVersion => 'Requires Android 8.0 or newer';
/// en: 'Picture-in-picture permission is disabled. Enable it in Settings > Apps > Plezy > Picture-in-picture'
String get permissionDisabled => 'Picture-in-picture permission is disabled. Enable it in Settings > Apps > Plezy > Picture-in-picture';
/// en: 'Device doesn't support picture-in-picture mode'
String get notSupported => 'Device doesn\'t support picture-in-picture mode';
/// en: 'Picture-in-picture failed to start'
String get failed => 'Picture-in-picture failed to start';
/// en: 'An error occurred: ${error}'
String unknown({required Object error}) => 'An error occurred: ${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class TranslationsLibrariesTabsEn { class TranslationsLibrariesTabsEn {
TranslationsLibrariesTabsEn._(this._root); TranslationsLibrariesTabsEn._(this._root);
@@ -2281,6 +2310,12 @@ extension on Translations {
'videoControls.timelineSlider' => 'Video timeline', 'videoControls.timelineSlider' => 'Video timeline',
'videoControls.volumeSlider' => 'Volume level', 'videoControls.volumeSlider' => 'Volume level',
'videoControls.backButton' => 'Back', 'videoControls.backButton' => 'Back',
'videoControls.pipFailed' => 'Picture-in-picture failed to start',
'videoControls.pipErrors.androidVersion' => 'Requires Android 8.0 or newer',
'videoControls.pipErrors.permissionDisabled' => 'Picture-in-picture permission is disabled. Enable it in Settings > Apps > Plezy > Picture-in-picture',
'videoControls.pipErrors.notSupported' => 'Device doesn\'t support picture-in-picture mode',
'videoControls.pipErrors.failed' => 'Picture-in-picture failed to start',
'videoControls.pipErrors.unknown' => ({required Object error}) => 'An error occurred: ${error}',
'userStatus.admin' => 'Admin', 'userStatus.admin' => 'Admin',
'userStatus.restricted' => 'Restricted', 'userStatus.restricted' => 'Restricted',
'userStatus.protected' => 'Protected', 'userStatus.protected' => 'Protected',
@@ -2525,14 +2560,14 @@ extension on Translations {
'watchTogether.watchingWithOthers' => 'Watching with others', 'watchTogether.watchingWithOthers' => 'Watching with others',
'watchTogether.endSession' => 'End Session', 'watchTogether.endSession' => 'End Session',
'watchTogether.leaveSession' => 'Leave Session', 'watchTogether.leaveSession' => 'Leave Session',
_ => null,
} ?? switch (path) {
'watchTogether.endSessionQuestion' => 'End Session?', 'watchTogether.endSessionQuestion' => 'End Session?',
'watchTogether.leaveSessionQuestion' => 'Leave Session?', 'watchTogether.leaveSessionQuestion' => 'Leave Session?',
'watchTogether.endSessionConfirm' => 'This will end the session for all participants.', 'watchTogether.endSessionConfirm' => 'This will end the session for all participants.',
'watchTogether.leaveSessionConfirm' => 'You will be removed from the session.', 'watchTogether.leaveSessionConfirm' => 'You will be removed from the session.',
'watchTogether.endSessionConfirmOverlay' => 'This will end the watch session for all participants.', 'watchTogether.endSessionConfirmOverlay' => 'This will end the watch session for all participants.',
'watchTogether.leaveSessionConfirmOverlay' => 'You will be disconnected from the watch session.', 'watchTogether.leaveSessionConfirmOverlay' => 'You will be disconnected from the watch session.',
_ => null,
} ?? switch (path) {
'watchTogether.end' => 'End', 'watchTogether.end' => 'End',
'watchTogether.leave' => 'Leave', 'watchTogether.leave' => 'Leave',
'watchTogether.syncing' => 'Syncing...', 'watchTogether.syncing' => 'Syncing...',
+24 -2
View File
@@ -441,6 +441,8 @@ class _TranslationsVideoControlsFr implements TranslationsVideoControlsEn {
@override String get timelineSlider => 'Timeline vidéo'; @override String get timelineSlider => 'Timeline vidéo';
@override String get volumeSlider => 'Niveau sonore'; @override String get volumeSlider => 'Niveau sonore';
@override String get backButton => 'Retour'; @override String get backButton => 'Retour';
@override String get pipFailed => 'Échec du démarrage du mode image dans l\'image';
@override late final _TranslationsVideoControlsPipErrorsFr pipErrors = _TranslationsVideoControlsPipErrorsFr._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -900,6 +902,20 @@ class _TranslationsHotkeysActionsFr implements TranslationsHotkeysActionsEn {
@override String get subSeekPrev => 'Rechercher le sous-titre précédent'; @override String get subSeekPrev => 'Rechercher le sous-titre précédent';
} }
// Path: videoControls.pipErrors
class _TranslationsVideoControlsPipErrorsFr implements TranslationsVideoControlsPipErrorsEn {
_TranslationsVideoControlsPipErrorsFr._(this._root);
final TranslationsFr _root; // ignore: unused_field
// Translations
@override String get androidVersion => 'Nécessite Android 8.0 ou plus récent';
@override String get permissionDisabled => 'L\'autorisation Image dans l\'image est désactivée. Activez-la dans Paramètres > Applications > Plezy > Image dans l\'image';
@override String get notSupported => 'Cet appareil ne prend pas en charge le mode image dans l\'image';
@override String get failed => 'Échec du démarrage du mode image dans l\'image';
@override String unknown({required Object error}) => 'Une erreur s\'est produite : ${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class _TranslationsLibrariesTabsFr implements TranslationsLibrariesTabsEn { class _TranslationsLibrariesTabsFr implements TranslationsLibrariesTabsEn {
_TranslationsLibrariesTabsFr._(this._root); _TranslationsLibrariesTabsFr._(this._root);
@@ -1198,6 +1214,12 @@ extension on TranslationsFr {
'videoControls.timelineSlider' => 'Timeline vidéo', 'videoControls.timelineSlider' => 'Timeline vidéo',
'videoControls.volumeSlider' => 'Niveau sonore', 'videoControls.volumeSlider' => 'Niveau sonore',
'videoControls.backButton' => 'Retour', 'videoControls.backButton' => 'Retour',
'videoControls.pipFailed' => 'Échec du démarrage du mode image dans l\'image',
'videoControls.pipErrors.androidVersion' => 'Nécessite Android 8.0 ou plus récent',
'videoControls.pipErrors.permissionDisabled' => 'L\'autorisation Image dans l\'image est désactivée. Activez-la dans Paramètres > Applications > Plezy > Image dans l\'image',
'videoControls.pipErrors.notSupported' => 'Cet appareil ne prend pas en charge le mode image dans l\'image',
'videoControls.pipErrors.failed' => 'Échec du démarrage du mode image dans l\'image',
'videoControls.pipErrors.unknown' => ({required Object error}) => 'Une erreur s\'est produite : ${error}',
'userStatus.admin' => 'Admin', 'userStatus.admin' => 'Admin',
'userStatus.restricted' => 'Restreint', 'userStatus.restricted' => 'Restreint',
'userStatus.protected' => 'Protégé', 'userStatus.protected' => 'Protégé',
@@ -1442,14 +1464,14 @@ extension on TranslationsFr {
'watchTogether.watchingWithOthers' => 'Regarder avec d\'autres personnes', 'watchTogether.watchingWithOthers' => 'Regarder avec d\'autres personnes',
'watchTogether.endSession' => 'Fin de session', 'watchTogether.endSession' => 'Fin de session',
'watchTogether.leaveSession' => 'Quitter la session', 'watchTogether.leaveSession' => 'Quitter la session',
_ => null,
} ?? switch (path) {
'watchTogether.endSessionQuestion' => 'Terminer la session ?', 'watchTogether.endSessionQuestion' => 'Terminer la session ?',
'watchTogether.leaveSessionQuestion' => 'Quitter la session ?', 'watchTogether.leaveSessionQuestion' => 'Quitter la session ?',
'watchTogether.endSessionConfirm' => 'Cela mettra fin à la session pour tous les participants.', 'watchTogether.endSessionConfirm' => 'Cela mettra fin à la session pour tous les participants.',
'watchTogether.leaveSessionConfirm' => 'Vous allez être déconnecté de la session.', 'watchTogether.leaveSessionConfirm' => 'Vous allez être déconnecté de la session.',
'watchTogether.endSessionConfirmOverlay' => 'Cela mettra fin à la session de visionnage pour tous les participants.', 'watchTogether.endSessionConfirmOverlay' => 'Cela mettra fin à la session de visionnage pour tous les participants.',
'watchTogether.leaveSessionConfirmOverlay' => 'Vous serez déconnecté de la session de visionnage.', 'watchTogether.leaveSessionConfirmOverlay' => 'Vous serez déconnecté de la session de visionnage.',
_ => null,
} ?? switch (path) {
'watchTogether.end' => 'Terminer', 'watchTogether.end' => 'Terminer',
'watchTogether.leave' => 'Fin', 'watchTogether.leave' => 'Fin',
'watchTogether.syncing' => 'Synchronisation...', 'watchTogether.syncing' => 'Synchronisation...',
+24 -2
View File
@@ -442,6 +442,8 @@ class _TranslationsVideoControlsIt implements TranslationsVideoControlsEn {
@override String get timelineSlider => 'Timeline video'; @override String get timelineSlider => 'Timeline video';
@override String get volumeSlider => 'Livello volume'; @override String get volumeSlider => 'Livello volume';
@override String get backButton => 'Indietro'; @override String get backButton => 'Indietro';
@override String get pipFailed => 'Impossibile avviare la modalità Picture-in-Picture';
@override late final _TranslationsVideoControlsPipErrorsIt pipErrors = _TranslationsVideoControlsPipErrorsIt._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -902,6 +904,20 @@ class _TranslationsHotkeysActionsIt implements TranslationsHotkeysActionsEn {
@override String get subSeekPrev => 'Vai al sottotitolo precedente'; @override String get subSeekPrev => 'Vai al sottotitolo precedente';
} }
// Path: videoControls.pipErrors
class _TranslationsVideoControlsPipErrorsIt implements TranslationsVideoControlsPipErrorsEn {
_TranslationsVideoControlsPipErrorsIt._(this._root);
final TranslationsIt _root; // ignore: unused_field
// Translations
@override String get androidVersion => 'Richiede Android 8.0 o versioni successive';
@override String get permissionDisabled => 'L\'autorizzazione Picture-in-Picture è disabilitata. Abilitala in Impostazioni > App > Plezy > Picture-in-Picture';
@override String get notSupported => 'Questo dispositivo non supporta la modalità Picture-in-Picture';
@override String get failed => 'Impossibile avviare la modalità Picture-in-Picture';
@override String unknown({required Object error}) => 'Si è verificato un errore: ${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class _TranslationsLibrariesTabsIt implements TranslationsLibrariesTabsEn { class _TranslationsLibrariesTabsIt implements TranslationsLibrariesTabsEn {
_TranslationsLibrariesTabsIt._(this._root); _TranslationsLibrariesTabsIt._(this._root);
@@ -1201,6 +1217,12 @@ extension on TranslationsIt {
'videoControls.timelineSlider' => 'Timeline video', 'videoControls.timelineSlider' => 'Timeline video',
'videoControls.volumeSlider' => 'Livello volume', 'videoControls.volumeSlider' => 'Livello volume',
'videoControls.backButton' => 'Indietro', 'videoControls.backButton' => 'Indietro',
'videoControls.pipFailed' => 'Impossibile avviare la modalità Picture-in-Picture',
'videoControls.pipErrors.androidVersion' => 'Richiede Android 8.0 o versioni successive',
'videoControls.pipErrors.permissionDisabled' => 'L\'autorizzazione Picture-in-Picture è disabilitata. Abilitala in Impostazioni > App > Plezy > Picture-in-Picture',
'videoControls.pipErrors.notSupported' => 'Questo dispositivo non supporta la modalità Picture-in-Picture',
'videoControls.pipErrors.failed' => 'Impossibile avviare la modalità Picture-in-Picture',
'videoControls.pipErrors.unknown' => ({required Object error}) => 'Si è verificato un errore: ${error}',
'userStatus.admin' => 'Admin', 'userStatus.admin' => 'Admin',
'userStatus.restricted' => 'Limitato', 'userStatus.restricted' => 'Limitato',
'userStatus.protected' => 'Protetto', 'userStatus.protected' => 'Protetto',
@@ -1444,14 +1466,14 @@ extension on TranslationsIt {
'watchTogether.joining' => 'Connessione...', 'watchTogether.joining' => 'Connessione...',
'watchTogether.controlMode' => 'Modalità di Controllo', 'watchTogether.controlMode' => 'Modalità di Controllo',
'watchTogether.controlModeQuestion' => 'Chi può controllare la riproduzione?', 'watchTogether.controlModeQuestion' => 'Chi può controllare la riproduzione?',
_ => null,
} ?? switch (path) {
'watchTogether.hostOnly' => 'Solo Host', 'watchTogether.hostOnly' => 'Solo Host',
'watchTogether.anyone' => 'Tutti', 'watchTogether.anyone' => 'Tutti',
'watchTogether.hostingSession' => 'Hosting Sessione', 'watchTogether.hostingSession' => 'Hosting Sessione',
'watchTogether.inSession' => 'In Sessione', 'watchTogether.inSession' => 'In Sessione',
'watchTogether.sessionCode' => 'Codice Sessione', 'watchTogether.sessionCode' => 'Codice Sessione',
'watchTogether.hostControlsPlayback' => 'L\'host controlla la riproduzione', 'watchTogether.hostControlsPlayback' => 'L\'host controlla la riproduzione',
_ => null,
} ?? switch (path) {
'watchTogether.anyoneCanControl' => 'Tutti possono controllare la riproduzione', 'watchTogether.anyoneCanControl' => 'Tutti possono controllare la riproduzione',
'watchTogether.hostControls' => 'Controllo host', 'watchTogether.hostControls' => 'Controllo host',
'watchTogether.anyoneControls' => 'Controllo di tutti', 'watchTogether.anyoneControls' => 'Controllo di tutti',
+24 -2
View File
@@ -442,6 +442,8 @@ class _TranslationsVideoControlsKo implements TranslationsVideoControlsEn {
@override String get timelineSlider => '타임라인'; @override String get timelineSlider => '타임라인';
@override String get volumeSlider => '볼륨 조절'; @override String get volumeSlider => '볼륨 조절';
@override String get backButton => '뒤로 가기'; @override String get backButton => '뒤로 가기';
@override String get pipFailed => '화면 속 화면 모드를 시작할 수 없습니다';
@override late final _TranslationsVideoControlsPipErrorsKo pipErrors = _TranslationsVideoControlsPipErrorsKo._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -902,6 +904,20 @@ class _TranslationsHotkeysActionsKo implements TranslationsHotkeysActionsEn {
@override String get subSeekPrev => '이전 자막으로 이동'; @override String get subSeekPrev => '이전 자막으로 이동';
} }
// Path: videoControls.pipErrors
class _TranslationsVideoControlsPipErrorsKo implements TranslationsVideoControlsPipErrorsEn {
_TranslationsVideoControlsPipErrorsKo._(this._root);
final TranslationsKo _root; // ignore: unused_field
// Translations
@override String get androidVersion => 'Android 8.0 이상이 필요합니다';
@override String get permissionDisabled => '화면 속 화면 권한이 비활성화되어 있습니다. 설정 > 앱 > Plezy > 화면 속 화면에서 활성화하세요';
@override String get notSupported => '이 기기는 화면 속 화면 모드를 지원하지 않습니다';
@override String get failed => '화면 속 화면 모드를 시작할 수 없습니다';
@override String unknown({required Object error}) => '오류가 발생했습니다: ${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class _TranslationsLibrariesTabsKo implements TranslationsLibrariesTabsEn { class _TranslationsLibrariesTabsKo implements TranslationsLibrariesTabsEn {
_TranslationsLibrariesTabsKo._(this._root); _TranslationsLibrariesTabsKo._(this._root);
@@ -1201,6 +1217,12 @@ extension on TranslationsKo {
'videoControls.timelineSlider' => '타임라인', 'videoControls.timelineSlider' => '타임라인',
'videoControls.volumeSlider' => '볼륨 조절', 'videoControls.volumeSlider' => '볼륨 조절',
'videoControls.backButton' => '뒤로 가기', 'videoControls.backButton' => '뒤로 가기',
'videoControls.pipFailed' => '화면 속 화면 모드를 시작할 수 없습니다',
'videoControls.pipErrors.androidVersion' => 'Android 8.0 이상이 필요합니다',
'videoControls.pipErrors.permissionDisabled' => '화면 속 화면 권한이 비활성화되어 있습니다. 설정 > 앱 > Plezy > 화면 속 화면에서 활성화하세요',
'videoControls.pipErrors.notSupported' => '이 기기는 화면 속 화면 모드를 지원하지 않습니다',
'videoControls.pipErrors.failed' => '화면 속 화면 모드를 시작할 수 없습니다',
'videoControls.pipErrors.unknown' => ({required Object error}) => '오류가 발생했습니다: ${error}',
'userStatus.admin' => '관리자', 'userStatus.admin' => '관리자',
'userStatus.restricted' => '제한됨', 'userStatus.restricted' => '제한됨',
'userStatus.protected' => '보호됨', 'userStatus.protected' => '보호됨',
@@ -1444,14 +1466,14 @@ extension on TranslationsKo {
'watchTogether.hostBadge' => '호스트', 'watchTogether.hostBadge' => '호스트',
'watchTogether.youAreHost' => '당신은 호스트 입니다', 'watchTogether.youAreHost' => '당신은 호스트 입니다',
'watchTogether.watchingWithOthers' => '다른 사람과 함께 시청 중', 'watchTogether.watchingWithOthers' => '다른 사람과 함께 시청 중',
_ => null,
} ?? switch (path) {
'watchTogether.endSession' => '세션 종료', 'watchTogether.endSession' => '세션 종료',
'watchTogether.leaveSession' => '세션 탈퇴', 'watchTogether.leaveSession' => '세션 탈퇴',
'watchTogether.endSessionQuestion' => '세션을 종료 하시겠습니까?', 'watchTogether.endSessionQuestion' => '세션을 종료 하시겠습니까?',
'watchTogether.leaveSessionQuestion' => '세션을 탈퇴 하시겠습니까?', 'watchTogether.leaveSessionQuestion' => '세션을 탈퇴 하시겠습니까?',
'watchTogether.endSessionConfirm' => '이 작업은 모든 참가자의 세션을 종료합니다.', 'watchTogether.endSessionConfirm' => '이 작업은 모든 참가자의 세션을 종료합니다.',
'watchTogether.leaveSessionConfirm' => '당신은 세션에서 제거됩니다.', 'watchTogether.leaveSessionConfirm' => '당신은 세션에서 제거됩니다.',
_ => null,
} ?? switch (path) {
'watchTogether.endSessionConfirmOverlay' => '이것은 모든 참가자의 시청 세션을 종료합니다.', 'watchTogether.endSessionConfirmOverlay' => '이것은 모든 참가자의 시청 세션을 종료합니다.',
'watchTogether.leaveSessionConfirmOverlay' => '시청 세션 연결이 끊어집니다.', 'watchTogether.leaveSessionConfirmOverlay' => '시청 세션 연결이 끊어집니다.',
'watchTogether.end' => '종료', 'watchTogether.end' => '종료',
+24 -2
View File
@@ -442,6 +442,8 @@ class _TranslationsVideoControlsNl implements TranslationsVideoControlsEn {
@override String get timelineSlider => 'Videotijdlijn'; @override String get timelineSlider => 'Videotijdlijn';
@override String get volumeSlider => 'Volumeniveau'; @override String get volumeSlider => 'Volumeniveau';
@override String get backButton => 'Terug'; @override String get backButton => 'Terug';
@override String get pipFailed => 'Beeld-in-beeld kon niet worden gestart';
@override late final _TranslationsVideoControlsPipErrorsNl pipErrors = _TranslationsVideoControlsPipErrorsNl._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -902,6 +904,20 @@ class _TranslationsHotkeysActionsNl implements TranslationsHotkeysActionsEn {
@override String get subSeekPrev => 'Naar vorige ondertitel'; @override String get subSeekPrev => 'Naar vorige ondertitel';
} }
// Path: videoControls.pipErrors
class _TranslationsVideoControlsPipErrorsNl implements TranslationsVideoControlsPipErrorsEn {
_TranslationsVideoControlsPipErrorsNl._(this._root);
final TranslationsNl _root; // ignore: unused_field
// Translations
@override String get androidVersion => 'Vereist Android 8.0 of nieuwer';
@override String get permissionDisabled => 'Beeld-in-beeld toestemming is uitgeschakeld. Schakel deze in via Instellingen > Apps > Plezy > Beeld-in-beeld';
@override String get notSupported => 'Dit apparaat ondersteunt geen beeld-in-beeld modus';
@override String get failed => 'Beeld-in-beeld kon niet worden gestart';
@override String unknown({required Object error}) => 'Er is een fout opgetreden: ${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class _TranslationsLibrariesTabsNl implements TranslationsLibrariesTabsEn { class _TranslationsLibrariesTabsNl implements TranslationsLibrariesTabsEn {
_TranslationsLibrariesTabsNl._(this._root); _TranslationsLibrariesTabsNl._(this._root);
@@ -1201,6 +1217,12 @@ extension on TranslationsNl {
'videoControls.timelineSlider' => 'Videotijdlijn', 'videoControls.timelineSlider' => 'Videotijdlijn',
'videoControls.volumeSlider' => 'Volumeniveau', 'videoControls.volumeSlider' => 'Volumeniveau',
'videoControls.backButton' => 'Terug', 'videoControls.backButton' => 'Terug',
'videoControls.pipFailed' => 'Beeld-in-beeld kon niet worden gestart',
'videoControls.pipErrors.androidVersion' => 'Vereist Android 8.0 of nieuwer',
'videoControls.pipErrors.permissionDisabled' => 'Beeld-in-beeld toestemming is uitgeschakeld. Schakel deze in via Instellingen > Apps > Plezy > Beeld-in-beeld',
'videoControls.pipErrors.notSupported' => 'Dit apparaat ondersteunt geen beeld-in-beeld modus',
'videoControls.pipErrors.failed' => 'Beeld-in-beeld kon niet worden gestart',
'videoControls.pipErrors.unknown' => ({required Object error}) => 'Er is een fout opgetreden: ${error}',
'userStatus.admin' => 'Beheerder', 'userStatus.admin' => 'Beheerder',
'userStatus.restricted' => 'Beperkt', 'userStatus.restricted' => 'Beperkt',
'userStatus.protected' => 'Beschermd', 'userStatus.protected' => 'Beschermd',
@@ -1444,14 +1466,14 @@ extension on TranslationsNl {
'watchTogether.joining' => 'Deelnemen...', 'watchTogether.joining' => 'Deelnemen...',
'watchTogether.controlMode' => 'Controlemodus', 'watchTogether.controlMode' => 'Controlemodus',
'watchTogether.controlModeQuestion' => 'Wie kan het afspelen bedienen?', 'watchTogether.controlModeQuestion' => 'Wie kan het afspelen bedienen?',
_ => null,
} ?? switch (path) {
'watchTogether.hostOnly' => 'Alleen Host', 'watchTogether.hostOnly' => 'Alleen Host',
'watchTogether.anyone' => 'Iedereen', 'watchTogether.anyone' => 'Iedereen',
'watchTogether.hostingSession' => 'Sessie Hosten', 'watchTogether.hostingSession' => 'Sessie Hosten',
'watchTogether.inSession' => 'In Sessie', 'watchTogether.inSession' => 'In Sessie',
'watchTogether.sessionCode' => 'Sessiecode', 'watchTogether.sessionCode' => 'Sessiecode',
'watchTogether.hostControlsPlayback' => 'Host bedient het afspelen', 'watchTogether.hostControlsPlayback' => 'Host bedient het afspelen',
_ => null,
} ?? switch (path) {
'watchTogether.anyoneCanControl' => 'Iedereen kan het afspelen bedienen', 'watchTogether.anyoneCanControl' => 'Iedereen kan het afspelen bedienen',
'watchTogether.hostControls' => 'Host bedient', 'watchTogether.hostControls' => 'Host bedient',
'watchTogether.anyoneControls' => 'Iedereen bedient', 'watchTogether.anyoneControls' => 'Iedereen bedient',
+24 -2
View File
@@ -442,6 +442,8 @@ class _TranslationsVideoControlsSv implements TranslationsVideoControlsEn {
@override String get timelineSlider => 'Videotidslinje'; @override String get timelineSlider => 'Videotidslinje';
@override String get volumeSlider => 'Volymnivå'; @override String get volumeSlider => 'Volymnivå';
@override String get backButton => 'Tillbaka'; @override String get backButton => 'Tillbaka';
@override String get pipFailed => 'Bild-i-bild kunde inte starta';
@override late final _TranslationsVideoControlsPipErrorsSv pipErrors = _TranslationsVideoControlsPipErrorsSv._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -902,6 +904,20 @@ class _TranslationsHotkeysActionsSv implements TranslationsHotkeysActionsEn {
@override String get subSeekPrev => 'Hoppa till föregående undertext'; @override String get subSeekPrev => 'Hoppa till föregående undertext';
} }
// Path: videoControls.pipErrors
class _TranslationsVideoControlsPipErrorsSv implements TranslationsVideoControlsPipErrorsEn {
_TranslationsVideoControlsPipErrorsSv._(this._root);
final TranslationsSv _root; // ignore: unused_field
// Translations
@override String get androidVersion => 'Kräver Android 8.0 eller nyare';
@override String get permissionDisabled => 'Bild-i-bild-behörighet är inaktiverad. Aktivera den i Inställningar > Appar > Plezy > Bild-i-bild';
@override String get notSupported => 'Denna enhet stöder inte bild-i-bild-läge';
@override String get failed => 'Bild-i-bild kunde inte starta';
@override String unknown({required Object error}) => 'Ett fel uppstod: ${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class _TranslationsLibrariesTabsSv implements TranslationsLibrariesTabsEn { class _TranslationsLibrariesTabsSv implements TranslationsLibrariesTabsEn {
_TranslationsLibrariesTabsSv._(this._root); _TranslationsLibrariesTabsSv._(this._root);
@@ -1201,6 +1217,12 @@ extension on TranslationsSv {
'videoControls.timelineSlider' => 'Videotidslinje', 'videoControls.timelineSlider' => 'Videotidslinje',
'videoControls.volumeSlider' => 'Volymnivå', 'videoControls.volumeSlider' => 'Volymnivå',
'videoControls.backButton' => 'Tillbaka', 'videoControls.backButton' => 'Tillbaka',
'videoControls.pipFailed' => 'Bild-i-bild kunde inte starta',
'videoControls.pipErrors.androidVersion' => 'Kräver Android 8.0 eller nyare',
'videoControls.pipErrors.permissionDisabled' => 'Bild-i-bild-behörighet är inaktiverad. Aktivera den i Inställningar > Appar > Plezy > Bild-i-bild',
'videoControls.pipErrors.notSupported' => 'Denna enhet stöder inte bild-i-bild-läge',
'videoControls.pipErrors.failed' => 'Bild-i-bild kunde inte starta',
'videoControls.pipErrors.unknown' => ({required Object error}) => 'Ett fel uppstod: ${error}',
'userStatus.admin' => 'Admin', 'userStatus.admin' => 'Admin',
'userStatus.restricted' => 'Begränsad', 'userStatus.restricted' => 'Begränsad',
'userStatus.protected' => 'Skyddad', 'userStatus.protected' => 'Skyddad',
@@ -1444,14 +1466,14 @@ extension on TranslationsSv {
'watchTogether.joining' => 'Ansluter...', 'watchTogether.joining' => 'Ansluter...',
'watchTogether.controlMode' => 'Kontrollläge', 'watchTogether.controlMode' => 'Kontrollläge',
'watchTogether.controlModeQuestion' => 'Vem kan styra uppspelningen?', 'watchTogether.controlModeQuestion' => 'Vem kan styra uppspelningen?',
_ => null,
} ?? switch (path) {
'watchTogether.hostOnly' => 'Endast Värd', 'watchTogether.hostOnly' => 'Endast Värd',
'watchTogether.anyone' => 'Alla', 'watchTogether.anyone' => 'Alla',
'watchTogether.hostingSession' => 'Värd för Session', 'watchTogether.hostingSession' => 'Värd för Session',
'watchTogether.inSession' => 'I Session', 'watchTogether.inSession' => 'I Session',
'watchTogether.sessionCode' => 'Sessionskod', 'watchTogether.sessionCode' => 'Sessionskod',
'watchTogether.hostControlsPlayback' => 'Värden styr uppspelningen', 'watchTogether.hostControlsPlayback' => 'Värden styr uppspelningen',
_ => null,
} ?? switch (path) {
'watchTogether.anyoneCanControl' => 'Alla kan styra uppspelningen', 'watchTogether.anyoneCanControl' => 'Alla kan styra uppspelningen',
'watchTogether.hostControls' => 'Värd styr', 'watchTogether.hostControls' => 'Värd styr',
'watchTogether.anyoneControls' => 'Alla styr', 'watchTogether.anyoneControls' => 'Alla styr',
+24 -2
View File
@@ -442,6 +442,8 @@ class _TranslationsVideoControlsZh implements TranslationsVideoControlsEn {
@override String get timelineSlider => '视频时间轴'; @override String get timelineSlider => '视频时间轴';
@override String get volumeSlider => '音量调节'; @override String get volumeSlider => '音量调节';
@override String get backButton => '返回'; @override String get backButton => '返回';
@override String get pipFailed => '画中画启动失败';
@override late final _TranslationsVideoControlsPipErrorsZh pipErrors = _TranslationsVideoControlsPipErrorsZh._(_root);
} }
// Path: userStatus // Path: userStatus
@@ -902,6 +904,20 @@ class _TranslationsHotkeysActionsZh implements TranslationsHotkeysActionsEn {
@override String get subSeekPrev => '跳转到上一字幕'; @override String get subSeekPrev => '跳转到上一字幕';
} }
// Path: videoControls.pipErrors
class _TranslationsVideoControlsPipErrorsZh implements TranslationsVideoControlsPipErrorsEn {
_TranslationsVideoControlsPipErrorsZh._(this._root);
final TranslationsZh _root; // ignore: unused_field
// Translations
@override String get androidVersion => '需要 Android 8.0 或更高版本';
@override String get permissionDisabled => '画中画权限已禁用。请在设置 > 应用 > Plezy > 画中画中启用';
@override String get notSupported => '此设备不支持画中画模式';
@override String get failed => '画中画启动失败';
@override String unknown({required Object error}) => '发生错误:${error}';
}
// Path: libraries.tabs // Path: libraries.tabs
class _TranslationsLibrariesTabsZh implements TranslationsLibrariesTabsEn { class _TranslationsLibrariesTabsZh implements TranslationsLibrariesTabsEn {
_TranslationsLibrariesTabsZh._(this._root); _TranslationsLibrariesTabsZh._(this._root);
@@ -1201,6 +1217,12 @@ extension on TranslationsZh {
'videoControls.timelineSlider' => '视频时间轴', 'videoControls.timelineSlider' => '视频时间轴',
'videoControls.volumeSlider' => '音量调节', 'videoControls.volumeSlider' => '音量调节',
'videoControls.backButton' => '返回', 'videoControls.backButton' => '返回',
'videoControls.pipFailed' => '画中画启动失败',
'videoControls.pipErrors.androidVersion' => '需要 Android 8.0 或更高版本',
'videoControls.pipErrors.permissionDisabled' => '画中画权限已禁用。请在设置 > 应用 > Plezy > 画中画中启用',
'videoControls.pipErrors.notSupported' => '此设备不支持画中画模式',
'videoControls.pipErrors.failed' => '画中画启动失败',
'videoControls.pipErrors.unknown' => ({required Object error}) => '发生错误:${error}',
'userStatus.admin' => '管理员', 'userStatus.admin' => '管理员',
'userStatus.restricted' => '受限', 'userStatus.restricted' => '受限',
'userStatus.protected' => '受保护', 'userStatus.protected' => '受保护',
@@ -1444,14 +1466,14 @@ extension on TranslationsZh {
'watchTogether.joining' => '加入中...', 'watchTogether.joining' => '加入中...',
'watchTogether.controlMode' => '控制模式', 'watchTogether.controlMode' => '控制模式',
'watchTogether.controlModeQuestion' => '谁可以控制播放?', 'watchTogether.controlModeQuestion' => '谁可以控制播放?',
_ => null,
} ?? switch (path) {
'watchTogether.hostOnly' => '仅主持人', 'watchTogether.hostOnly' => '仅主持人',
'watchTogether.anyone' => '任何人', 'watchTogether.anyone' => '任何人',
'watchTogether.hostingSession' => '主持会话', 'watchTogether.hostingSession' => '主持会话',
'watchTogether.inSession' => '在会话中', 'watchTogether.inSession' => '在会话中',
'watchTogether.sessionCode' => '会话代码', 'watchTogether.sessionCode' => '会话代码',
'watchTogether.hostControlsPlayback' => '主持人控制播放', 'watchTogether.hostControlsPlayback' => '主持人控制播放',
_ => null,
} ?? switch (path) {
'watchTogether.anyoneCanControl' => '任何人都可以控制播放', 'watchTogether.anyoneCanControl' => '任何人都可以控制播放',
'watchTogether.hostControls' => '主持人控制', 'watchTogether.hostControls' => '主持人控制',
'watchTogether.anyoneControls' => '任何人控制', 'watchTogether.anyoneControls' => '任何人控制',
+9 -1
View File
@@ -290,7 +290,15 @@
"rotationLockButton": "Rotationslås", "rotationLockButton": "Rotationslås",
"timelineSlider": "Videotidslinje", "timelineSlider": "Videotidslinje",
"volumeSlider": "Volymnivå", "volumeSlider": "Volymnivå",
"backButton": "Tillbaka" "backButton": "Tillbaka",
"pipFailed": "Bild-i-bild kunde inte starta",
"pipErrors": {
"androidVersion": "Kräver Android 8.0 eller nyare",
"permissionDisabled": "Bild-i-bild-behörighet är inaktiverad. Aktivera den i Inställningar > Appar > Plezy > Bild-i-bild",
"notSupported": "Denna enhet stöder inte bild-i-bild-läge",
"failed": "Bild-i-bild kunde inte starta",
"unknown": "Ett fel uppstod: ${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "Admin", "admin": "Admin",
+9 -1
View File
@@ -290,7 +290,15 @@
"rotationLockButton": "旋转锁定", "rotationLockButton": "旋转锁定",
"timelineSlider": "视频时间轴", "timelineSlider": "视频时间轴",
"volumeSlider": "音量调节", "volumeSlider": "音量调节",
"backButton": "返回" "backButton": "返回",
"pipFailed": "画中画启动失败",
"pipErrors": {
"androidVersion": "需要 Android 8.0 或更高版本",
"permissionDisabled": "画中画权限已禁用。请在设置 > 应用 > Plezy > 画中画中启用",
"notSupported": "此设备不支持画中画模式",
"failed": "画中画启动失败",
"unknown": "发生错误:${error}"
}
}, },
"userStatus": { "userStatus": {
"admin": "管理员", "admin": "管理员",
+5 -4
View File
@@ -858,10 +858,11 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
); );
} }
void _togglePIPMode() { Future<void> _togglePIPMode() async {
setState(() { final result = await _videoPIPManager?.togglePIP();
_videoPIPManager?.togglePIP(); if (result != null && !result.$1 && mounted) {
}); showErrorSnackBar(context, result.$2 ?? t.videoControls.pipFailed);
}
} }
/// Cycle through BoxFit modes: contain → cover → fill → contain (for button) /// Cycle through BoxFit modes: contain → cover → fill → contain (for button)
+21 -2
View File
@@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:plezy/i18n/strings.g.dart';
class PipService { class PipService {
static const MethodChannel _channel = MethodChannel('app.plezy/pip'); static const MethodChannel _channel = MethodChannel('app.plezy/pip');
@@ -29,7 +30,25 @@ class PipService {
return await _channel.invokeMethod<bool>('isSupported') ?? false; return await _channel.invokeMethod<bool>('isSupported') ?? false;
} }
static Future<void> enter({int? width, int? height}) async { static Future<(bool success, String? error)> enter({int? width, int? height}) async {
await _channel.invokeMethod('enter', {'width': width, 'height': height}); final result = await _channel.invokeMethod<Map>('enter', {'width': width, 'height': height});
if (result == null) {
return (false, t.videoControls.pipErrors.unknown(error: 'No response'));
}
final success = result['success'] as bool? ?? false;
final errorCode = result['errorCode'] as String?;
final errorMessage = result['errorMessage'] as String?;
final error = errorCode != null ? _getLocalizedError(errorCode, errorMessage) : null;
return (success, error);
}
static String _getLocalizedError(String errorCode, String? errorMessage) {
return switch (errorCode) {
'android_version' => t.videoControls.pipErrors.androidVersion,
'permission_disabled' => t.videoControls.pipErrors.permissionDisabled,
'not_supported' => t.videoControls.pipErrors.notSupported,
'failed' => t.videoControls.pipErrors.failed,
_ => t.videoControls.pipErrors.unknown(error: errorMessage ?? 'Unknown error'),
};
} }
} }
+4 -4
View File
@@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../mpv/mpv.dart'; import '../mpv/mpv.dart';
import '../services/pip_service.dart'; import '../services/pip_service.dart';
@@ -16,9 +15,10 @@ class VideoPIPManager {
ValueNotifier<bool> get isPipActive => PipService().isPipActive; ValueNotifier<bool> get isPipActive => PipService().isPipActive;
/// Toggle native PiP /// Toggle native PiP
Future<void> togglePIP() async { /// Returns a tuple of (success, error message) for error handling
Future<(bool success, String? error)> togglePIP() async {
final supported = await PipService.isSupported(); final supported = await PipService.isSupported();
if (!supported) return; if (!supported) return (false, 'PiP not supported on this device');
// Try to get actual video dimensions from MPV // Try to get actual video dimensions from MPV
int? width; int? width;
@@ -39,6 +39,6 @@ class VideoPIPManager {
width ??= _playerSize?.width.toInt(); width ??= _playerSize?.width.toInt();
height ??= _playerSize?.height.toInt(); height ??= _playerSize?.height.toInt();
await PipService.enter(width: width, height: height); return await PipService.enter(width: width, height: height);
} }
} }