diff --git a/appimage/AppRun b/appimage/AppRun index 95b7c05..6eccc8d 100755 --- a/appimage/AppRun +++ b/appimage/AppRun @@ -1,4 +1,4 @@ #!/bin/sh cd "$(dirname "$0")" -exec ./fluffychat \ No newline at end of file +exec ./extera_next diff --git a/appimage/Extera.AppDir/.DirIcon b/appimage/Extera.AppDir/.DirIcon new file mode 120000 index 0000000..483c081 --- /dev/null +++ b/appimage/Extera.AppDir/.DirIcon @@ -0,0 +1 @@ +extera.svg \ No newline at end of file diff --git a/appimage/Extera.AppDir/AppRun b/appimage/Extera.AppDir/AppRun new file mode 100755 index 0000000..6eccc8d --- /dev/null +++ b/appimage/Extera.AppDir/AppRun @@ -0,0 +1,4 @@ +#!/bin/sh + +cd "$(dirname "$0")" +exec ./extera_next diff --git a/appimage/FluffyChat.desktop b/appimage/Extera.AppDir/Extera.desktop similarity index 59% rename from appimage/FluffyChat.desktop rename to appimage/Extera.AppDir/Extera.desktop index ceee4c9..81cabe1 100644 --- a/appimage/FluffyChat.desktop +++ b/appimage/Extera.AppDir/Extera.desktop @@ -1,9 +1,9 @@ [Desktop Entry] Type=Application Version=1.0 -Name=FluffyChat +Name=Extera Next Comment=Matrix Client. Chat with your friends Exec=AppRun -Icon=fluffychat +Icon=extera Terminal=false -Categories=Network;Chat;InstantMessaging;X-Matrix; \ No newline at end of file +Categories=Network;Chat;InstantMessaging;X-Matrix; diff --git a/appimage/Extera.AppDir/data/flutter_assets/AssetManifest.bin b/appimage/Extera.AppDir/data/flutter_assets/AssetManifest.bin new file mode 100644 index 0000000..7b2603b --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/AssetManifest.bin @@ -0,0 +1 @@ + assets/banner.png  assetassets/banner.pngassets/banner_transparent.png  assetassets/banner_transparent.pngassets/favicon.png  assetassets/favicon.pngassets/info-logo.png  assetassets/info-logo.pngassets/js/olm.zip  assetassets/js/olm.zipassets/logo.png  assetassets/logo.pngassets/logo.svg  assetassets/logo.svgassets/logo_transparent.png  assetassets/logo_transparent.pngassets/sas-emoji.json  assetassets/sas-emoji.jsonassets/sounds/call.ogg  assetassets/sounds/call.oggassets/sounds/notification.ogg  assetassets/sounds/notification.oggassets/sounds/phone.ogg  assetassets/sounds/phone.ogg2packages/cupertino_icons/assets/CupertinoIcons.ttf  asset2packages/cupertino_icons/assets/CupertinoIcons.ttf4packages/flutter_map/lib/assets/flutter_map_logo.png  asset4packages/flutter_map/lib/assets/flutter_map_logo.png2packages/handy_window/assets/handy-window-dark.css  asset2packages/handy_window/assets/handy-window-dark.css-packages/handy_window/assets/handy-window.css  asset-packages/handy_window/assets/handy-window.css(packages/material/lib/fonts/material.ttf  asset(packages/material/lib/fonts/material.ttf7packages/record_web/assets/js/record.fixwebmduration.js  asset7packages/record_web/assets/js/record.fixwebmduration.js/packages/record_web/assets/js/record.worklet.js  asset/packages/record_web/assets/js/record.worklet.js)packages/wakelock_plus/assets/no_sleep.js  asset)packages/wakelock_plus/assets/no_sleep.js \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/AssetManifest.json b/appimage/Extera.AppDir/data/flutter_assets/AssetManifest.json new file mode 100644 index 0000000..7dfe5ad --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/AssetManifest.json @@ -0,0 +1 @@ +{"assets/banner.png":["assets/banner.png"],"assets/banner_transparent.png":["assets/banner_transparent.png"],"assets/favicon.png":["assets/favicon.png"],"assets/info-logo.png":["assets/info-logo.png"],"assets/js/olm.zip":["assets/js/olm.zip"],"assets/logo.png":["assets/logo.png"],"assets/logo.svg":["assets/logo.svg"],"assets/logo_transparent.png":["assets/logo_transparent.png"],"assets/sas-emoji.json":["assets/sas-emoji.json"],"assets/sounds/call.ogg":["assets/sounds/call.ogg"],"assets/sounds/notification.ogg":["assets/sounds/notification.ogg"],"assets/sounds/phone.ogg":["assets/sounds/phone.ogg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_map/lib/assets/flutter_map_logo.png":["packages/flutter_map/lib/assets/flutter_map_logo.png"],"packages/handy_window/assets/handy-window-dark.css":["packages/handy_window/assets/handy-window-dark.css"],"packages/handy_window/assets/handy-window.css":["packages/handy_window/assets/handy-window.css"],"packages/material/lib/fonts/material.ttf":["packages/material/lib/fonts/material.ttf"],"packages/record_web/assets/js/record.fixwebmduration.js":["packages/record_web/assets/js/record.fixwebmduration.js"],"packages/record_web/assets/js/record.worklet.js":["packages/record_web/assets/js/record.worklet.js"],"packages/wakelock_plus/assets/no_sleep.js":["packages/wakelock_plus/assets/no_sleep.js"]} \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/FontManifest.json b/appimage/Extera.AppDir/data/flutter_assets/FontManifest.json new file mode 100644 index 0000000..9899cce --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/FontManifest.json @@ -0,0 +1 @@ +[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/material/Material","fonts":[{"asset":"packages/material/lib/fonts/material.ttf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}] \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/NOTICES.Z b/appimage/Extera.AppDir/data/flutter_assets/NOTICES.Z new file mode 100644 index 0000000..4855464 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/NOTICES.Z differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/NativeAssetsManifest.json b/appimage/Extera.AppDir/data/flutter_assets/NativeAssetsManifest.json new file mode 100644 index 0000000..523bfc7 --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/NativeAssetsManifest.json @@ -0,0 +1 @@ +{"format-version":[1,0,0],"native-assets":{}} \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/banner.png b/appimage/Extera.AppDir/data/flutter_assets/assets/banner.png new file mode 100644 index 0000000..8e1bb36 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/banner.png differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/banner_transparent.png b/appimage/Extera.AppDir/data/flutter_assets/assets/banner_transparent.png new file mode 100644 index 0000000..8e1bb36 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/banner_transparent.png differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/favicon.png b/appimage/Extera.AppDir/data/flutter_assets/assets/favicon.png new file mode 100644 index 0000000..61d0656 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/favicon.png differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/info-logo.png b/appimage/Extera.AppDir/data/flutter_assets/assets/info-logo.png new file mode 100644 index 0000000..61d0656 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/info-logo.png differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/js/olm.zip b/appimage/Extera.AppDir/data/flutter_assets/assets/js/olm.zip new file mode 100644 index 0000000..8537307 --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/assets/js/olm.zip @@ -0,0 +1 @@ +Not Found \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/logo.png b/appimage/Extera.AppDir/data/flutter_assets/assets/logo.png new file mode 100644 index 0000000..61d0656 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/logo.png differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/logo.svg b/appimage/Extera.AppDir/data/flutter_assets/assets/logo.svg new file mode 100644 index 0000000..767a86a --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/assets/logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/logo_transparent.png b/appimage/Extera.AppDir/data/flutter_assets/assets/logo_transparent.png new file mode 100644 index 0000000..61d0656 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/logo_transparent.png differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/sas-emoji.json b/appimage/Extera.AppDir/data/flutter_assets/assets/sas-emoji.json new file mode 100644 index 0000000..f0eb702 --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/assets/sas-emoji.json @@ -0,0 +1,2178 @@ +[ + { + "number": 0, + "emoji": "🐶", + "description": "Dog", + "unicode": "U+1F436", + "translated_descriptions": { + "ar": "كَلب", + "bg": "Куче", + "ca": "Gos", + "cs": "Pes", + "de": "Hund", + "eo": "Hundo", + "es": "Perro", + "et": "Koer", + "fi": "Koira", + "fr": "Chien", + "hr": "pas", + "hu": "Kutya", + "it": "Cane", + "ja": "犬", + "nb_NO": "Hund", + "nl": "Hond", + "pt_BR": "Cachorro", + "ru": "Собака", + "si": "බල්ලා", + "sk": "Hlava psa", + "sr": "пас", + "sv": "Hund", + "szl": null, + "tzm": "Aydi", + "uk": "Пес", + "zh_Hans": "狗" + } + }, + { + "number": 1, + "emoji": "🐱", + "description": "Cat", + "unicode": "U+1F431", + "translated_descriptions": { + "ar": "هِرَّة", + "bg": "Котка", + "ca": "Gat", + "cs": "Kočka", + "de": "Katze", + "eo": "Kato", + "es": "Gato", + "et": "Kass", + "fi": "Kissa", + "fr": "Chat", + "hr": "mačka", + "hu": "Macska", + "it": "Gatto", + "ja": "猫", + "nb_NO": "Katt", + "nl": "Kat", + "pt_BR": "Gato", + "ru": "Кошка", + "si": "පූසා", + "sk": "Hlava mačky", + "sr": "мачка", + "sv": "Katt", + "szl": null, + "tzm": "Amuc", + "uk": "Кіт", + "zh_Hans": "猫" + } + }, + { + "number": 2, + "emoji": "🦁", + "description": "Lion", + "unicode": "U+1F981", + "translated_descriptions": { + "ar": "أَسَد", + "bg": "Лъв", + "ca": "Lleó", + "cs": "Lev", + "de": "Löwe", + "eo": "Leono", + "es": "León", + "et": "Lõvi", + "fi": "Leijona", + "fr": "Lion", + "hr": "lav", + "hu": "Oroszlán", + "it": "Leone", + "ja": "ライオン", + "nb_NO": "Løve", + "nl": "Leeuw", + "pt_BR": "Leão", + "ru": "Лев", + "si": "සිංහයා", + "sk": "Hlava leva", + "sr": "лав", + "sv": "Lejon", + "szl": null, + "tzm": "Izem", + "uk": "Лев", + "zh_Hans": "狮子" + } + }, + { + "number": 3, + "emoji": "🐎", + "description": "Horse", + "unicode": "U+1F40E", + "translated_descriptions": { + "ar": "حِصَان", + "bg": "Кон", + "ca": "Cavall", + "cs": "Kůň", + "de": "Pferd", + "eo": "Ĉevalo", + "es": "Caballo", + "et": "Hobune", + "fi": "Hevonen", + "fr": "Cheval", + "hr": "konj", + "hu": "Ló", + "it": "Cavallo", + "ja": "馬", + "nb_NO": "Hest", + "nl": "Paard", + "pt_BR": "Cavalo", + "ru": "Лошадь", + "si": "අශ්වයා", + "sk": "Kôň", + "sr": "коњ", + "sv": "Häst", + "szl": null, + "tzm": "Ayyis", + "uk": "Кінь", + "zh_Hans": "马" + } + }, + { + "number": 4, + "emoji": "🦄", + "description": "Unicorn", + "unicode": "U+1F984", + "translated_descriptions": { + "ar": "حِصَانٌ بِقَرن", + "bg": "Еднорог", + "ca": "Unicorn", + "cs": "Jednorožec", + "de": "Einhorn", + "eo": "Unukorno", + "es": "Unicornio", + "et": "Ükssarvik", + "fi": "Yksisarvinen", + "fr": "Licorne", + "hr": "jednorog", + "hu": "Egyszarvú", + "it": "Unicorno", + "ja": "ユニコーン", + "nb_NO": "Enhjørning", + "nl": "Eenhoorn", + "pt_BR": "Unicórnio", + "ru": "Единорог", + "si": null, + "sk": "Hlava jednorožca", + "sr": "једнорог", + "sv": "Enhörning", + "szl": null, + "tzm": null, + "uk": "Єдиноріг", + "zh_Hans": "独角兽" + } + }, + { + "number": 5, + "emoji": "🐷", + "description": "Pig", + "unicode": "U+1F437", + "translated_descriptions": { + "ar": "خِنزِير", + "bg": "Прасе", + "ca": "Porc", + "cs": "Prase", + "de": "Schwein", + "eo": "Porko", + "es": "Cerdo", + "et": "Siga", + "fi": "Sika", + "fr": "Cochon", + "hr": "svinja", + "hu": "Malac", + "it": "Maiale", + "ja": "ブタ", + "nb_NO": "Gris", + "nl": "Varken", + "pt_BR": "Porco", + "ru": "Свинья", + "si": null, + "sk": "Hlava prasaťa", + "sr": "прасе", + "sv": "Gris", + "szl": null, + "tzm": "Ilef", + "uk": "Свиня", + "zh_Hans": "猪" + } + }, + { + "number": 6, + "emoji": "🐘", + "description": "Elephant", + "unicode": "U+1F418", + "translated_descriptions": { + "ar": "فِيل", + "bg": "Слон", + "ca": "Elefant", + "cs": "Slon", + "de": "Elefant", + "eo": "Elefanto", + "es": "Elefante", + "et": "Elevant", + "fi": "Norsu", + "fr": "Éléphant", + "hr": "slon", + "hu": "Elefánt", + "it": "Elefante", + "ja": "ゾウ", + "nb_NO": "Elefant", + "nl": "Olifant", + "pt_BR": "Elefante", + "ru": "Слон", + "si": null, + "sk": "Slon", + "sr": "слон", + "sv": "Elefant", + "szl": null, + "tzm": "Ilu", + "uk": "Слон", + "zh_Hans": "大象" + } + }, + { + "number": 7, + "emoji": "🐰", + "description": "Rabbit", + "unicode": "U+1F430", + "translated_descriptions": { + "ar": "أَرنَب", + "bg": "Заек", + "ca": "Conill", + "cs": "Králík", + "de": "Hase", + "eo": "Kuniklo", + "es": "Conejo", + "et": "Jänes", + "fi": "Kani", + "fr": "Lapin", + "hr": "zec", + "hu": "Nyúl", + "it": "Coniglio", + "ja": "うさぎ", + "nb_NO": "Kanin", + "nl": "Konijn", + "pt_BR": "Coelho", + "ru": "Кролик", + "si": null, + "sk": "Hlava zajaca", + "sr": "зец", + "sv": "Kanin", + "szl": null, + "tzm": "Agnin", + "uk": "Кріль", + "zh_Hans": "兔子" + } + }, + { + "number": 8, + "emoji": "🐼", + "description": "Panda", + "unicode": "U+1F43C", + "translated_descriptions": { + "ar": "باندَا", + "bg": "Панда", + "ca": "Panda", + "cs": "Panda", + "de": "Panda", + "eo": "Pando", + "es": "Panda", + "et": "Panda", + "fi": "Panda", + "fr": "Panda", + "hr": "panda", + "hu": "Panda", + "it": "Panda", + "ja": "パンダ", + "nb_NO": "Panda", + "nl": "Panda", + "pt_BR": "Panda", + "ru": "Панда", + "si": null, + "sk": "Hlava pandy", + "sr": "панда", + "sv": "Panda", + "szl": null, + "tzm": null, + "uk": "Панда", + "zh_Hans": "熊猫" + } + }, + { + "number": 9, + "emoji": "🐓", + "description": "Rooster", + "unicode": "U+1F413", + "translated_descriptions": { + "ar": "دِيك", + "bg": "Петел", + "ca": "Gall", + "cs": "Kohout", + "de": "Hahn", + "eo": "Virkoko", + "es": "Gallo", + "et": "Kukk", + "fi": "Kukko", + "fr": "Coq", + "hr": "kokot", + "hu": "Kakas", + "it": "Gallo", + "ja": "ニワトリ", + "nb_NO": "Hane", + "nl": "Haan", + "pt_BR": "Galo", + "ru": "Петух", + "si": null, + "sk": "Kohút", + "sr": "петао", + "sv": "Tupp", + "szl": null, + "tzm": "Ayaẓiḍ", + "uk": "Когут", + "zh_Hans": "公鸡" + } + }, + { + "number": 10, + "emoji": "🐧", + "description": "Penguin", + "unicode": "U+1F427", + "translated_descriptions": { + "ar": "بِطريق", + "bg": "Пингвин", + "ca": "Pingüí", + "cs": "Tučňák", + "de": "Pinguin", + "eo": "Pingveno", + "es": "Pingüino", + "et": "Pingviin", + "fi": "Pingviini", + "fr": "Manchot", + "hr": "pingvin", + "hu": "Pingvin", + "it": "Pinguino", + "ja": "ペンギン", + "nb_NO": "Pingvin", + "nl": "Pinguïn", + "pt_BR": "Pinguim", + "ru": "Пингвин", + "si": null, + "sk": "Tučniak", + "sr": "пингвин", + "sv": "Pingvin", + "szl": null, + "tzm": null, + "uk": "Пінгвін", + "zh_Hans": "企鹅" + } + }, + { + "number": 11, + "emoji": "🐢", + "description": "Turtle", + "unicode": "U+1F422", + "translated_descriptions": { + "ar": "سُلحفاة", + "bg": "Костенурка", + "ca": "Tortuga", + "cs": "Želva", + "de": "Schildkröte", + "eo": "Testudo", + "es": "Tortuga", + "et": "Kilpkonn", + "fi": "Kilpikonna", + "fr": "Tortue", + "hr": "kornjača", + "hu": "Teknős", + "it": "Tartaruga", + "ja": "亀", + "nb_NO": "Skilpadde", + "nl": "Schildpad", + "pt_BR": "Tartaruga", + "ru": "Черепаха", + "si": null, + "sk": "Korytnačka", + "sr": "корњача", + "sv": "Sköldpadda", + "szl": null, + "tzm": "Ifker", + "uk": "Черепаха", + "zh_Hans": "乌龟" + } + }, + { + "number": 12, + "emoji": "🐟", + "description": "Fish", + "unicode": "U+1F41F", + "translated_descriptions": { + "ar": "سَمَكَة", + "bg": "Риба", + "ca": "Peix", + "cs": "Ryba", + "de": "Fisch", + "eo": "Fiŝo", + "es": "Pez", + "et": "Kala", + "fi": "Kala", + "fr": "Poisson", + "hr": "riba", + "hu": "Hal", + "it": "Pesce", + "ja": "魚", + "nb_NO": "Fisk", + "nl": "Vis", + "pt_BR": "Peixe", + "ru": "Рыба", + "si": null, + "sk": "Ryba", + "sr": "риба", + "sv": "Fisk", + "szl": null, + "tzm": "Aselm", + "uk": "Риба", + "zh_Hans": "鱼" + } + }, + { + "number": 13, + "emoji": "🐙", + "description": "Octopus", + "unicode": "U+1F419", + "translated_descriptions": { + "ar": "أُخطُبُوط", + "bg": "Октопод", + "ca": "Pop", + "cs": "Chobotnice", + "de": "Oktopus", + "eo": "Polpo", + "es": "Pulpo", + "et": "Kaheksajalg", + "fi": "Tursas", + "fr": "Poulpe", + "hr": "hobotnica", + "hu": "Polip", + "it": "Polpo", + "ja": "たこ", + "nb_NO": "Blekksprut", + "nl": "Octopus", + "pt_BR": "Polvo", + "ru": "Осьминог", + "si": null, + "sk": "Chobotnica", + "sr": "октопод", + "sv": "Bläckfisk", + "szl": null, + "tzm": null, + "uk": "Восьминіг", + "zh_Hans": "章鱼" + } + }, + { + "number": 14, + "emoji": "🦋", + "description": "Butterfly", + "unicode": "U+1F98B", + "translated_descriptions": { + "ar": "فَرَاشَة", + "bg": "Пеперуда", + "ca": "Papallona", + "cs": "Motýl", + "de": "Schmetterling", + "eo": "Papilio", + "es": "Mariposa", + "et": "Liblikas", + "fi": "Perhonen", + "fr": "Papillon", + "hr": "leptir", + "hu": "Pillangó", + "it": "Farfalla", + "ja": "ちょうちょ", + "nb_NO": "Sommerfugl", + "nl": "Vlinder", + "pt_BR": "Borboleta", + "ru": "Бабочка", + "si": null, + "sk": "Motýľ", + "sr": "лептир", + "sv": "Fjäril", + "szl": null, + "tzm": null, + "uk": "Метелик", + "zh_Hans": "蝴蝶" + } + }, + { + "number": 15, + "emoji": "🌷", + "description": "Flower", + "unicode": "U+1F337", + "translated_descriptions": { + "ar": "زَهرَة", + "bg": "Цвете", + "ca": "Flor", + "cs": "Květina", + "de": "Blume", + "eo": "Floro", + "es": "Flor", + "et": "Lill", + "fi": "Kukka", + "fr": "Fleur", + "hr": "svijet", + "hu": "Virág", + "it": "Fiore", + "ja": "花", + "nb_NO": "Blomst", + "nl": "Bloem", + "pt_BR": "Flor", + "ru": "Цветок", + "si": null, + "sk": "Tulipán", + "sr": "цвет", + "sv": "Blomma", + "szl": null, + "tzm": null, + "uk": "Квітка", + "zh_Hans": "花" + } + }, + { + "number": 16, + "emoji": "🌳", + "description": "Tree", + "unicode": "U+1F333", + "translated_descriptions": { + "ar": "شَجَرَة", + "bg": "Дърво", + "ca": "Arbre", + "cs": "Strom", + "de": "Baum", + "eo": "Arbo", + "es": "Árbol", + "et": "Puu", + "fi": "Puu", + "fr": "Arbre", + "hr": "drvo", + "hu": "Fa", + "it": "Albero", + "ja": "木", + "nb_NO": "Tre", + "nl": "Boom", + "pt_BR": "Árvore", + "ru": "Дерево", + "si": null, + "sk": "Listnatý strom", + "sr": "дрво", + "sv": "Träd", + "szl": null, + "tzm": "Aseklu", + "uk": "Дерево", + "zh_Hans": "树" + } + }, + { + "number": 17, + "emoji": "🌵", + "description": "Cactus", + "unicode": "U+1F335", + "translated_descriptions": { + "ar": "صبار", + "bg": "Кактус", + "ca": "Cactus", + "cs": "Kaktus", + "de": "Kaktus", + "eo": "Kakto", + "es": "Cactus", + "et": "Kaktus", + "fi": "Kaktus", + "fr": "Cactus", + "hr": "kaktus", + "hu": "Kaktusz", + "it": "Cactus", + "ja": "サボテン", + "nb_NO": "Kaktus", + "nl": "Cactus", + "pt_BR": "Cacto", + "ru": "Кактус", + "si": null, + "sk": "Kaktus", + "sr": "кактус", + "sv": "Kaktus", + "szl": null, + "tzm": null, + "uk": "Кактус", + "zh_Hans": "仙人掌" + } + }, + { + "number": 18, + "emoji": "🍄", + "description": "Mushroom", + "unicode": "U+1F344", + "translated_descriptions": { + "ar": "فُطر", + "bg": "Гъба", + "ca": "Bolet", + "cs": "Houba", + "de": "Pilz", + "eo": "Fungo", + "es": "Seta", + "et": "Seen", + "fi": "Sieni", + "fr": "Champignon", + "hr": "gljiva", + "hu": "Gomba", + "it": "Fungo", + "ja": "きのこ", + "nb_NO": "Sopp", + "nl": "Paddenstoel", + "pt_BR": "Cogumelo", + "ru": "Гриб", + "si": null, + "sk": "Huba", + "sr": "печурка", + "sv": "Svamp", + "szl": null, + "tzm": "Agursel", + "uk": "Гриб", + "zh_Hans": "蘑菇" + } + }, + { + "number": 19, + "emoji": "🌏", + "description": "Globe", + "unicode": "U+1F30F", + "translated_descriptions": { + "ar": "كُرَةٌ أرضِيَّة", + "bg": "Глобус", + "ca": "Globus terraqüi", + "cs": "Zeměkoule", + "de": "Globus", + "eo": "Globo", + "es": "Globo", + "et": "Maakera", + "fi": "Maapallo", + "fr": "Globe", + "hr": "Globus", + "hu": "Földgömb", + "it": "Globo", + "ja": "地球", + "nb_NO": "Globus", + "nl": "Wereldbol", + "pt_BR": "Globo", + "ru": "Глобус", + "si": null, + "sk": "Zemeguľa", + "sr": "глобус", + "sv": "Jordklot", + "szl": null, + "tzm": null, + "uk": "Глобус", + "zh_Hans": "地球" + } + }, + { + "number": 20, + "emoji": "🌙", + "description": "Moon", + "unicode": "U+1F319", + "translated_descriptions": { + "ar": "قَمَر", + "bg": "Луна", + "ca": "Lluna", + "cs": "Měsíc", + "de": "Mond", + "eo": "Luno", + "es": "Luna", + "et": "Kuu", + "fi": "Kuu", + "fr": "Lune", + "hr": "mjesec", + "hu": "Hold", + "it": "Luna", + "ja": "月", + "nb_NO": "Måne", + "nl": "Maan", + "pt_BR": "Lua", + "ru": "Луна", + "si": null, + "sk": "Polmesiac", + "sr": "месец", + "sv": "Måne", + "szl": null, + "tzm": "Ayyur", + "uk": "Місяць", + "zh_Hans": "月亮" + } + }, + { + "number": 21, + "emoji": "☁️", + "description": "Cloud", + "unicode": "U+2601U+FE0F", + "translated_descriptions": { + "ar": "سَحابَة", + "bg": "Облак", + "ca": "Núvol", + "cs": "Mrak", + "de": "Wolke", + "eo": "Nubo", + "es": "Nube", + "et": "Pilv", + "fi": "Pilvi", + "fr": "Nuage", + "hr": "oblak", + "hu": "Felhő", + "it": "Nuvola", + "ja": "雲", + "nb_NO": "Sky", + "nl": "Wolk", + "pt_BR": "Nuvem", + "ru": "Облако", + "si": null, + "sk": "Oblak", + "sr": "облак", + "sv": "Moln", + "szl": null, + "tzm": null, + "uk": "Хмара", + "zh_Hans": "云" + } + }, + { + "number": 22, + "emoji": "🔥", + "description": "Fire", + "unicode": "U+1F525", + "translated_descriptions": { + "ar": "نار", + "bg": "Огън", + "ca": "Foc", + "cs": "Oheň", + "de": "Feuer", + "eo": "Fajro", + "es": "Fuego", + "et": "Tuli", + "fi": "Tuli", + "fr": "Feu", + "hr": "vatra", + "hu": "Tűz", + "it": "Fuoco", + "ja": "炎", + "nb_NO": "Flamme", + "nl": "Vuur", + "pt_BR": "Fogo", + "ru": "Огонь", + "si": null, + "sk": "Oheň", + "sr": "ватра", + "sv": "Eld", + "szl": null, + "tzm": "Timessi", + "uk": "Вогонь", + "zh_Hans": "火" + } + }, + { + "number": 23, + "emoji": "🍌", + "description": "Banana", + "unicode": "U+1F34C", + "translated_descriptions": { + "ar": "مَوزَة", + "bg": "Банан", + "ca": "Plàtan", + "cs": "Banán", + "de": "Banane", + "eo": "Banano", + "es": "Plátano", + "et": "Banaan", + "fi": "Banaani", + "fr": "Banane", + "hr": "banana", + "hu": "Banán", + "it": "Banana", + "ja": "バナナ", + "nb_NO": "Banan", + "nl": "Banaan", + "pt_BR": "Banana", + "ru": "Банан", + "si": null, + "sk": "Banán", + "sr": "банана", + "sv": "Banan", + "szl": null, + "tzm": "Tabanant", + "uk": "Банан", + "zh_Hans": "香蕉" + } + }, + { + "number": 24, + "emoji": "🍎", + "description": "Apple", + "unicode": "U+1F34E", + "translated_descriptions": { + "ar": "تُفَّاحَة", + "bg": "Ябълка", + "ca": "Poma", + "cs": "Jablko", + "de": "Apfel", + "eo": "Pomo", + "es": "Manzana", + "et": "Õun", + "fi": "Omena", + "fr": "Pomme", + "hr": "jabuka", + "hu": "Alma", + "it": "Mela", + "ja": "リンゴ", + "nb_NO": "Eple", + "nl": "Appel", + "pt_BR": "Maçã", + "ru": "Яблоко", + "si": null, + "sk": "Červené jablko", + "sr": "јабука", + "sv": "Äpple", + "szl": null, + "tzm": "Tadeffuyt", + "uk": "Яблуко", + "zh_Hans": "苹果" + } + }, + { + "number": 25, + "emoji": "🍓", + "description": "Strawberry", + "unicode": "U+1F353", + "translated_descriptions": { + "ar": "فَراوِلَة", + "bg": "Ягода", + "ca": "Maduixa", + "cs": "Jahoda", + "de": "Erdbeere", + "eo": "Frago", + "es": "Fresa", + "et": "Maasikas", + "fi": "Mansikka", + "fr": "Fraise", + "hr": "jagoda", + "hu": "Eper", + "it": "Fragola", + "ja": "いちご", + "nb_NO": "Jordbær", + "nl": "Aardbei", + "pt_BR": "Morango", + "ru": "Клубника", + "si": null, + "sk": "Jahoda", + "sr": "јагода", + "sv": "Jordgubbe", + "szl": null, + "tzm": null, + "uk": "Полуниця", + "zh_Hans": "草莓" + } + }, + { + "number": 26, + "emoji": "🌽", + "description": "Corn", + "unicode": "U+1F33D", + "translated_descriptions": { + "ar": "ذُرَة", + "bg": "Царевица", + "ca": "Blat de moro", + "cs": "Kukuřice", + "de": "Mais", + "eo": "Maizo", + "es": "Maíz", + "et": "Mais", + "fi": "Maissi", + "fr": "Maïs", + "hr": "kukuruza", + "hu": "Kukorica", + "it": "Mais", + "ja": "とうもろこし", + "nb_NO": "Mais", + "nl": "Maïs", + "pt_BR": "Milho", + "ru": "Кукуруза", + "si": null, + "sk": "Kukuričný klas", + "sr": "кукуруз", + "sv": "Majs", + "szl": null, + "tzm": null, + "uk": "Кукурудза", + "zh_Hans": "玉米" + } + }, + { + "number": 27, + "emoji": "🍕", + "description": "Pizza", + "unicode": "U+1F355", + "translated_descriptions": { + "ar": "بِيتزا", + "bg": "Пица", + "ca": "Pizza", + "cs": "Pizza", + "de": "Pizza", + "eo": "Pico", + "es": "Pizza", + "et": "Pitsa", + "fi": "Pizza", + "fr": "Pizza", + "hr": "pizza", + "hu": "Pizza", + "it": "Pizza", + "ja": "ピザ", + "nb_NO": "Pizza", + "nl": "Pizza", + "pt_BR": "Pizza", + "ru": "Пицца", + "si": null, + "sk": "Pizza", + "sr": "пица", + "sv": "Pizza", + "szl": null, + "tzm": null, + "uk": "Піца", + "zh_Hans": "披萨" + } + }, + { + "number": 28, + "emoji": "🎂", + "description": "Cake", + "unicode": "U+1F382", + "translated_descriptions": { + "ar": "كَعكَة", + "bg": "Торта", + "ca": "Pastís", + "cs": "Dort", + "de": "Kuchen", + "eo": "Torto", + "es": "Tarta", + "et": "Kook", + "fi": "Kakku", + "fr": "Gâteau", + "hr": "torta", + "hu": "Süti", + "it": "Torta", + "ja": "ケーキ", + "nb_NO": "Kake", + "nl": "Taart", + "pt_BR": "Bolo", + "ru": "Торт", + "si": null, + "sk": "Narodeninová torta", + "sr": "торта", + "sv": "Tårta", + "szl": null, + "tzm": null, + "uk": "Пиріг", + "zh_Hans": "蛋糕" + } + }, + { + "number": 29, + "emoji": "❤️", + "description": "Heart", + "unicode": "U+2764U+FE0F", + "translated_descriptions": { + "ar": "قَلب", + "bg": "Сърце", + "ca": "Cor", + "cs": "Srdce", + "de": "Herz", + "eo": "Koro", + "es": "Corazón", + "et": "Süda", + "fi": "Sydän", + "fr": "Cœur", + "hr": "srca", + "hu": "Szív", + "it": "Cuore", + "ja": "ハート", + "nb_NO": "Hjerte", + "nl": "Hart", + "pt_BR": "Coração", + "ru": "Сердце", + "si": null, + "sk": "červené srdce", + "sr": "срце", + "sv": "Hjärta", + "szl": null, + "tzm": "Ul", + "uk": "Серце", + "zh_Hans": "心" + } + }, + { + "number": 30, + "emoji": "😀", + "description": "Smiley", + "unicode": "U+1F600", + "translated_descriptions": { + "ar": "اِبتِسَامَة", + "bg": "Усмивка", + "ca": "Somrient", + "cs": "Smajlík", + "de": "Lächeln", + "eo": "Rideto", + "es": "Emoticono", + "et": "Smaili", + "fi": "Hymynaama", + "fr": "Sourire", + "hr": "smajlića", + "hu": "Mosoly", + "it": "Faccina sorridente", + "ja": "スマイル", + "nb_NO": "Smilefjes", + "nl": "Smiley", + "pt_BR": "Sorriso", + "ru": "Улыбка", + "si": null, + "sk": "Škeriaca sa tvár", + "sr": "смајли", + "sv": "Smiley", + "szl": null, + "tzm": null, + "uk": "Посмішка", + "zh_Hans": "笑脸" + } + }, + { + "number": 31, + "emoji": "🤖", + "description": "Robot", + "unicode": "U+1F916", + "translated_descriptions": { + "ar": "رُوبُوت", + "bg": "Робот", + "ca": "Robot", + "cs": "Robot", + "de": "Roboter", + "eo": "Roboto", + "es": "Robot", + "et": "Robot", + "fi": "Robotti", + "fr": "Robot", + "hr": "robot", + "hu": "Robot", + "it": "Robot", + "ja": "ロボと", + "nb_NO": "Robot", + "nl": "Robot", + "pt_BR": "Robô", + "ru": "Робот", + "si": null, + "sk": "Robot", + "sr": "робот", + "sv": "Robot", + "szl": null, + "tzm": "Aṛubu", + "uk": "Робот", + "zh_Hans": "机器人" + } + }, + { + "number": 32, + "emoji": "🎩", + "description": "Hat", + "unicode": "U+1F3A9", + "translated_descriptions": { + "ar": "قُبَّعَة", + "bg": "Шапка", + "ca": "Barret", + "cs": "Klobouk", + "de": "Hut", + "eo": "Ĉapelo", + "es": "Sombrero", + "et": "Kübar", + "fi": "Hattu", + "fr": "Chapeau", + "hr": "kapa", + "hu": "Kalap", + "it": "Cappello", + "ja": "帽子", + "nb_NO": "Hatt", + "nl": "Hoed", + "pt_BR": "Chapéu", + "ru": "Шляпа", + "si": null, + "sk": "Cilinder", + "sr": "шешир", + "sv": "Hatt", + "szl": null, + "tzm": "Taraza", + "uk": "Капелюх", + "zh_Hans": "帽子" + } + }, + { + "number": 33, + "emoji": "👓", + "description": "Glasses", + "unicode": "U+1F453", + "translated_descriptions": { + "ar": "نَظَّارَة", + "bg": "Очила", + "ca": "Ulleres", + "cs": "Brýle", + "de": "Brille", + "eo": "Okulvitroj", + "es": "Gafas", + "et": "Prillid", + "fi": "Silmälasit", + "fr": "Lunettes", + "hr": "naočale", + "hu": "Szemüveg", + "it": "Occhiali", + "ja": "めがね", + "nb_NO": "Briller", + "nl": "Bril", + "pt_BR": "Óculos", + "ru": "Очки", + "si": null, + "sk": "Okuliare", + "sr": "наочаре", + "sv": "Glasögon", + "szl": null, + "tzm": null, + "uk": "Окуляри", + "zh_Hans": "眼镜" + } + }, + { + "number": 34, + "emoji": "🔧", + "description": "Spanner", + "unicode": "U+1F527", + "translated_descriptions": { + "ar": "مِفتَاحُ رَبط", + "bg": "Гаечен ключ", + "ca": "Clau anglesa", + "cs": "Klíč", + "de": "Schraubenschlüssel", + "eo": "Ŝraŭbŝlosilo", + "es": "Llave inglesa", + "et": "Mutrivõti", + "fi": "Kiintoavain", + "fr": "Clé à molette", + "hr": "ključ", + "hu": "Csavarkulcs", + "it": "Chiave inglese", + "ja": "スパナ", + "nb_NO": "Fastnøkkel", + "nl": "Moersleutel", + "pt_BR": "Chave inglesa", + "ru": "Ключ", + "si": null, + "sk": "Francúzsky kľúč", + "sr": "кључ", + "sv": "Skruvnyckel", + "szl": null, + "tzm": null, + "uk": "Гайковий ключ", + "zh_Hans": "扳手" + } + }, + { + "number": 35, + "emoji": "🎅", + "description": "Santa", + "unicode": "U+1F385", + "translated_descriptions": { + "ar": "سانتا", + "bg": "Дядо Коледа", + "ca": "Pare Noél", + "cs": "Mikuláš", + "de": "Weihnachtsmann", + "eo": "Kristnaska viro", + "es": "Papá Noel", + "et": "Jõuluvana", + "fi": "Joulupukki", + "fr": "Père Noël", + "hr": "deda Mraz", + "hu": "Télapó", + "it": "Babbo Natale", + "ja": "サンタ", + "nb_NO": "Julenisse", + "nl": "Kerstman", + "pt_BR": "Papai-noel", + "ru": "Санта", + "si": null, + "sk": "Santa Claus", + "sr": "деда Мраз", + "sv": "Tomte", + "szl": null, + "tzm": null, + "uk": "Санта Клаус", + "zh_Hans": "圣诞老人" + } + }, + { + "number": 36, + "emoji": "👍", + "description": "Thumbs Up", + "unicode": "U+1F44D", + "translated_descriptions": { + "ar": "رَفعُ إِبهَام", + "bg": "Палец нагоре", + "ca": "Polzes amunt", + "cs": "Palec nahoru", + "de": "Daumen Hoch", + "eo": "Dikfingro supren", + "es": "Pulgar arriba", + "et": "Pöidlad püsti", + "fi": "Peukalo ylös", + "fr": "Pouce en l’air", + "hr": "palac gore", + "hu": "Hüvelykujj fel", + "it": "Pollice alzato", + "ja": "いいね", + "nb_NO": "Tommel Opp", + "nl": "Duim omhoog", + "pt_BR": "Joinha", + "ru": "Большой палец вверх", + "si": null, + "sk": "Palec nahor", + "sr": "палчић горе", + "sv": "Tummen upp", + "szl": null, + "tzm": null, + "uk": "Великий палець вгору", + "zh_Hans": "赞" + } + }, + { + "number": 37, + "emoji": "☂️", + "description": "Umbrella", + "unicode": "U+2602U+FE0F", + "translated_descriptions": { + "ar": "مِظَلَّة", + "bg": "Чадър", + "ca": "Paraigües", + "cs": "Deštník", + "de": "Regenschirm", + "eo": "Ombrelo", + "es": "Paraguas", + "et": "Vihmavari", + "fi": "Sateenvarjo", + "fr": "Parapluie", + "hr": "kišobran", + "hu": "Esernyő", + "it": "Ombrello", + "ja": "傘", + "nb_NO": "Paraply", + "nl": "Paraplu", + "pt_BR": "Guarda-chuva", + "ru": "Зонт", + "si": null, + "sk": "Dáždnik", + "sr": "кишобран", + "sv": "Paraply", + "szl": null, + "tzm": null, + "uk": "Парасолька", + "zh_Hans": "伞" + } + }, + { + "number": 38, + "emoji": "⌛", + "description": "Hourglass", + "unicode": "U+231B", + "translated_descriptions": { + "ar": "سَاعَةٌ رَملِيَّة", + "bg": "Пясъчен часовник", + "ca": "Rellotge de sorra", + "cs": "Přesýpací hodiny", + "de": "Sanduhr", + "eo": "Sablohorloĝo", + "es": "Reloj de arena", + "et": "Liivakell", + "fi": "Tiimalasi", + "fr": "Sablier", + "hr": "pješčani sat", + "hu": "Homokóra", + "it": "Clessidra", + "ja": "砂時計", + "nb_NO": "Timeglass", + "nl": "Zandloper", + "pt_BR": "Ampulheta", + "ru": "Песочные часы", + "si": null, + "sk": "Presýpacie hodiny", + "sr": "пешчаник", + "sv": "Timglas", + "szl": null, + "tzm": null, + "uk": "Пісковий годинник", + "zh_Hans": "沙漏" + } + }, + { + "number": 39, + "emoji": "⏰", + "description": "Clock", + "unicode": "U+23F0", + "translated_descriptions": { + "ar": "سَاعَة", + "bg": "Часовник", + "ca": "Rellotge", + "cs": "Hodiny", + "de": "Uhr", + "eo": "Horloĝo", + "es": "Reloj", + "et": "Kell", + "fi": "Pöytäkello", + "fr": "Réveil", + "hr": "sat", + "hu": "Óra", + "it": "Orologio", + "ja": "時計", + "nb_NO": "Klokke", + "nl": "Wekker", + "pt_BR": "Relógio", + "ru": "Часы", + "si": null, + "sk": "Budík", + "sr": "сат", + "sv": "Klocka", + "szl": null, + "tzm": null, + "uk": "Годинник", + "zh_Hans": "时钟" + } + }, + { + "number": 40, + "emoji": "🎁", + "description": "Gift", + "unicode": "U+1F381", + "translated_descriptions": { + "ar": "هَدِيَّة", + "bg": "Подарък", + "ca": "Regal", + "cs": "Dárek", + "de": "Geschenk", + "eo": "Donaco", + "es": "Regalo", + "et": "Kingitus", + "fi": "Lahja", + "fr": "Cadeau", + "hr": "poklon", + "hu": "Ajándék", + "it": "Regalo", + "ja": "ギフト", + "nb_NO": "Gave", + "nl": "Geschenk", + "pt_BR": "Presente", + "ru": "Подарок", + "si": null, + "sk": "Zabalený darček", + "sr": "поклон", + "sv": "Present", + "szl": null, + "tzm": null, + "uk": "Подарунок", + "zh_Hans": "礼物" + } + }, + { + "number": 41, + "emoji": "💡", + "description": "Light Bulb", + "unicode": "U+1F4A1", + "translated_descriptions": { + "ar": "مِصبَاح", + "bg": "Лампа", + "ca": "Bombeta", + "cs": "Žárovka", + "de": "Glühbirne", + "eo": "Lampo", + "es": "Bombilla", + "et": "Lambipirn", + "fi": "Hehkulamppu", + "fr": "Ampoule", + "hr": "žarulja", + "hu": "Égő", + "it": "Lampadina", + "ja": "電球", + "nb_NO": "Lyspære", + "nl": "Gloeilamp", + "pt_BR": "Lâmpada", + "ru": "Лампочка", + "si": null, + "sk": "Žiarovka", + "sr": "сијалица", + "sv": "Lampa", + "szl": null, + "tzm": null, + "uk": "Лампочка", + "zh_Hans": "灯泡" + } + }, + { + "number": 42, + "emoji": "📕", + "description": "Book", + "unicode": "U+1F4D5", + "translated_descriptions": { + "ar": "كِتَاب", + "bg": "Книга", + "ca": "Llibre", + "cs": "Kniha", + "de": "Buch", + "eo": "Libro", + "es": "Libro", + "et": "Raamat", + "fi": "Kirja", + "fr": "Livre", + "hr": "knjiga", + "hu": "Könyv", + "it": "Libro", + "ja": "本", + "nb_NO": "Bok", + "nl": "Boek", + "pt_BR": "Livro", + "ru": "Книга", + "si": null, + "sk": "Zatvorená kniha", + "sr": "књига", + "sv": "Bok", + "szl": null, + "tzm": "Adlis", + "uk": "Книга", + "zh_Hans": "书" + } + }, + { + "number": 43, + "emoji": "✏️", + "description": "Pencil", + "unicode": "U+270FU+FE0F", + "translated_descriptions": { + "ar": "قَلَمُ رَصاص", + "bg": "Молив", + "ca": "Llapis", + "cs": "Tužka", + "de": "Bleistift", + "eo": "Krajono", + "es": "Lápiz", + "et": "Pliiats", + "fi": "Lyijykynä", + "fr": "Crayon", + "hr": "olovka", + "hu": "Ceruza", + "it": "Matita", + "ja": "鉛筆", + "nb_NO": "Blyant", + "nl": "Potlood", + "pt_BR": "Lápis", + "ru": "Карандаш", + "si": null, + "sk": "Ceruzka", + "sr": "оловка", + "sv": "Penna", + "szl": null, + "tzm": null, + "uk": "Олівець", + "zh_Hans": "铅笔" + } + }, + { + "number": 44, + "emoji": "📎", + "description": "Paperclip", + "unicode": "U+1F4CE", + "translated_descriptions": { + "ar": "مِشبَكُ وَرَق", + "bg": "Кламер", + "ca": "Clip", + "cs": "Sponka", + "de": "Büroklammer", + "eo": "Paperkuntenilo", + "es": "Clip", + "et": "Kirjaklamber", + "fi": "Paperiliitin", + "fr": "Trombone", + "hr": "spajalica", + "hu": "Gémkapocs", + "it": "Graffetta", + "ja": "クリップ", + "nb_NO": "BInders", + "nl": "Papierklemmetje", + "pt_BR": "Clipe de papel", + "ru": "Скрепка", + "si": null, + "sk": "Sponka na papier", + "sr": "спајалица", + "sv": "Gem", + "szl": null, + "tzm": null, + "uk": "Спиначка", + "zh_Hans": "回形针" + } + }, + { + "number": 45, + "emoji": "✂️", + "description": "Scissors", + "unicode": "U+2702U+FE0F", + "translated_descriptions": { + "ar": "مِقَصّ", + "bg": "Ножици", + "ca": "Tisores", + "cs": "Nůžky", + "de": "Schere", + "eo": "Tondilo", + "es": "Tijeras", + "et": "Käärid", + "fi": "Sakset", + "fr": "Ciseaux", + "hr": "škare", + "hu": "Olló", + "it": "Forbici", + "ja": "はさみ", + "nb_NO": "Saks", + "nl": "Schaar", + "pt_BR": "Tesoura", + "ru": "Ножницы", + "si": null, + "sk": "Nožnice", + "sr": "маказе", + "sv": "Sax", + "szl": null, + "tzm": null, + "uk": "Ножиці", + "zh_Hans": "剪刀" + } + }, + { + "number": 46, + "emoji": "🔒", + "description": "Lock", + "unicode": "U+1F512", + "translated_descriptions": { + "ar": "قُفل", + "bg": "Катинар", + "ca": "Cadenat", + "cs": "Zámek", + "de": "Schloss", + "eo": "Seruro", + "es": "Candado", + "et": "Lukk", + "fi": "Lukko", + "fr": "Cadenas", + "hr": "zaključati", + "hu": "Lakat", + "it": "Lucchetto", + "ja": "錠前", + "nb_NO": "Lås", + "nl": "Slot", + "pt_BR": "Cadeado", + "ru": "Замок", + "si": null, + "sk": "Zatvorená zámka", + "sr": "катанац", + "sv": "Lås", + "szl": null, + "tzm": null, + "uk": "Замок", + "zh_Hans": "锁" + } + }, + { + "number": 47, + "emoji": "🔑", + "description": "Key", + "unicode": "U+1F511", + "translated_descriptions": { + "ar": "مِفتَاح", + "bg": "Ключ", + "ca": "Clau", + "cs": "Klíč", + "de": "Schlüssel", + "eo": "Ŝlosilo", + "es": "Llave", + "et": "Võti", + "fi": "Avain", + "fr": "Clé", + "hr": "ključ", + "hu": "Kulcs", + "it": "Chiave", + "ja": "鍵", + "nb_NO": "Nøkkel", + "nl": "Sleutel", + "pt_BR": "Chave", + "ru": "Ключ", + "si": null, + "sk": "Kľúč", + "sr": "кључ", + "sv": "Nyckel", + "szl": null, + "tzm": "Tasarut", + "uk": "Ключ", + "zh_Hans": "钥匙" + } + }, + { + "number": 48, + "emoji": "🔨", + "description": "Hammer", + "unicode": "U+1F528", + "translated_descriptions": { + "ar": "مِطرَقَة", + "bg": "Чук", + "ca": "Martell", + "cs": "Kladivo", + "de": "Hammer", + "eo": "Martelo", + "es": "Martillo", + "et": "Haamer", + "fi": "Vasara", + "fr": "Marteau", + "hr": "čekić", + "hu": "Kalapács", + "it": "Martello", + "ja": "金槌", + "nb_NO": "Hammer", + "nl": "Hamer", + "pt_BR": "Martelo", + "ru": "Молоток", + "si": null, + "sk": "Kladivo", + "sr": "чекић", + "sv": "Hammare", + "szl": null, + "tzm": null, + "uk": "Молоток", + "zh_Hans": "锤子" + } + }, + { + "number": 49, + "emoji": "☎️", + "description": "Telephone", + "unicode": "U+260EU+FE0F", + "translated_descriptions": { + "ar": "تِلِفُون", + "bg": "Телефон", + "ca": "Telèfon", + "cs": "Telefon", + "de": "Telefon", + "eo": "Telefono", + "es": "Telefono", + "et": "Telefon", + "fi": "Puhelin", + "fr": "Téléphone", + "hr": "telefon", + "hu": "Telefon", + "it": "Telefono", + "ja": "電話機", + "nb_NO": "Telefon", + "nl": "Telefoon", + "pt_BR": "Telefone", + "ru": "Телефон", + "si": null, + "sk": "Telefón", + "sr": "телефон", + "sv": "Telefon", + "szl": null, + "tzm": "Atilifun", + "uk": "Телефон", + "zh_Hans": "电话" + } + }, + { + "number": 50, + "emoji": "🏁", + "description": "Flag", + "unicode": "U+1F3C1", + "translated_descriptions": { + "ar": "عَلَم", + "bg": "Флаг", + "ca": "Bandera", + "cs": "Vlajka", + "de": "Flagge", + "eo": "Flago", + "es": "Bandera", + "et": "Lipp", + "fi": "Lippu", + "fr": "Drapeau", + "hr": "zastava", + "hu": "Zászló", + "it": "Bandiera", + "ja": "旗", + "nb_NO": "Flagg", + "nl": "Vlag", + "pt_BR": "Bandeira", + "ru": "Флаг", + "si": null, + "sk": "Kockovaná zástava", + "sr": "застава", + "sv": "Flagga", + "szl": null, + "tzm": "Acenyal", + "uk": "Прапор", + "zh_Hans": "旗帜" + } + }, + { + "number": 51, + "emoji": "🚂", + "description": "Train", + "unicode": "U+1F682", + "translated_descriptions": { + "ar": "قِطَار", + "bg": "Влак", + "ca": "Tren", + "cs": "Vlak", + "de": "Zug", + "eo": "Vagonaro", + "es": "Tren", + "et": "Rong", + "fi": "Juna", + "fr": "Train", + "hr": "vlak", + "hu": "Vonat", + "it": "Treno", + "ja": "電車", + "nb_NO": "Tog", + "nl": "Trein", + "pt_BR": "Trem", + "ru": "Поезд", + "si": null, + "sk": "Rušeň", + "sr": "воз", + "sv": "Tåg", + "szl": null, + "tzm": null, + "uk": "Потяг", + "zh_Hans": "火车" + } + }, + { + "number": 52, + "emoji": "🚲", + "description": "Bicycle", + "unicode": "U+1F6B2", + "translated_descriptions": { + "ar": "دَرّاجَة", + "bg": "Колело", + "ca": "Bicicleta", + "cs": "Kolo", + "de": "Fahrrad", + "eo": "Biciklo", + "es": "Bicicleta", + "et": "Jalgratas", + "fi": "Polkupyörä", + "fr": "Vélo", + "hr": "bicikl", + "hu": "Kerékpár", + "it": "Bicicletta", + "ja": "自転車", + "nb_NO": "Sykkel", + "nl": "Fiets", + "pt_BR": "Bicicleta", + "ru": "Велосипед", + "si": null, + "sk": "Bicykel", + "sr": "бицикл", + "sv": "Cykel", + "szl": null, + "tzm": null, + "uk": "Велосипед", + "zh_Hans": "自行车" + } + }, + { + "number": 53, + "emoji": "✈️", + "description": "Aeroplane", + "unicode": "U+2708U+FE0F", + "translated_descriptions": { + "ar": "طَائِرة", + "bg": "Самолет", + "ca": "Avió", + "cs": "Letadlo", + "de": "Flugzeug", + "eo": "Aviadilo", + "es": "Avión", + "et": "Lennuk", + "fi": "Lentokone", + "fr": "Avion", + "hr": "avion", + "hu": "Repülő", + "it": "Aeroplano", + "ja": "飛行機", + "nb_NO": "Fly", + "nl": "Vliegtuig", + "pt_BR": "Avião", + "ru": "Самолет", + "si": null, + "sk": "Lietadlo", + "sr": "авион", + "sv": "Flygplan", + "szl": null, + "tzm": null, + "uk": "Літак", + "zh_Hans": "飞机" + } + }, + { + "number": 54, + "emoji": "🚀", + "description": "Rocket", + "unicode": "U+1F680", + "translated_descriptions": { + "ar": "صَارُوخ", + "bg": "Ракета", + "ca": "Coet", + "cs": "Raketa", + "de": "Rakete", + "eo": "Raketo", + "es": "Cohete", + "et": "Rakett", + "fi": "Raketti", + "fr": "Fusée", + "hr": "raketa", + "hu": "Rakáta", + "it": "Razzo", + "ja": "ロケット", + "nb_NO": "Rakett", + "nl": "Raket", + "pt_BR": "Foguete", + "ru": "Ракета", + "si": null, + "sk": "Raketa", + "sr": "ракета", + "sv": "Raket", + "szl": null, + "tzm": null, + "uk": "Ракета", + "zh_Hans": "火箭" + } + }, + { + "number": 55, + "emoji": "🏆", + "description": "Trophy", + "unicode": "U+1F3C6", + "translated_descriptions": { + "ar": "كَأسُ النَّصر", + "bg": "Трофей", + "ca": "Trofeu", + "cs": "Pohár", + "de": "Pokal", + "eo": "Trofeo", + "es": "Trofeo", + "et": "Auhind", + "fi": "Palkinto", + "fr": "Trophée", + "hr": "trofej", + "hu": "Trófea", + "it": "Trofeo", + "ja": "トロフィー", + "nb_NO": "Pokal", + "nl": "Trofee", + "pt_BR": "Troféu", + "ru": "Кубок", + "si": null, + "sk": "Trofej", + "sr": "пехар", + "sv": "Trofé", + "szl": null, + "tzm": null, + "uk": "Приз", + "zh_Hans": "奖杯" + } + }, + { + "number": 56, + "emoji": "⚽", + "description": "Ball", + "unicode": "U+26BD", + "translated_descriptions": { + "ar": "كُرَة", + "bg": "Топка", + "ca": "Pilota", + "cs": "Míč", + "de": "Ball", + "eo": "Pilko", + "es": "Bola", + "et": "Pall", + "fi": "Pallo", + "fr": "Ballon", + "hr": "lopta", + "hu": "Labda", + "it": "Palla", + "ja": "ボール", + "nb_NO": "Ball", + "nl": "Bal", + "pt_BR": "Bola", + "ru": "Мяч", + "si": null, + "sk": "Futbal", + "sr": "лопта", + "sv": "Boll", + "szl": null, + "tzm": "Tcama", + "uk": "М'яч", + "zh_Hans": "球" + } + }, + { + "number": 57, + "emoji": "🎸", + "description": "Guitar", + "unicode": "U+1F3B8", + "translated_descriptions": { + "ar": "غيتار", + "bg": "Китара", + "ca": "Guitarra", + "cs": "Kytara", + "de": "Gitarre", + "eo": "Gitaro", + "es": "Guitarra", + "et": "Kitarr", + "fi": "Kitara", + "fr": "Guitare", + "hr": "gitara", + "hu": "Gitár", + "it": "Chitarra", + "ja": "ギター", + "nb_NO": "Gitar", + "nl": "Gitaar", + "pt_BR": "Guitarra", + "ru": "Гитара", + "si": null, + "sk": "Gitara", + "sr": "гитара", + "sv": "Gitarr", + "szl": null, + "tzm": "Agiṭaṛ", + "uk": "Гітара", + "zh_Hans": "吉他" + } + }, + { + "number": 58, + "emoji": "🎺", + "description": "Trumpet", + "unicode": "U+1F3BA", + "translated_descriptions": { + "ar": "بُوق", + "bg": "Тромпет", + "ca": "Trompeta", + "cs": "Trumpeta", + "de": "Trompete", + "eo": "Trumpeto", + "es": "Trompeta", + "et": "Trompet", + "fi": "Trumpetti", + "fr": "Trompette", + "hr": "truba", + "hu": "Trombita", + "it": "Trombetta", + "ja": "トランペット", + "nb_NO": "Trompet", + "nl": "Trompet", + "pt_BR": "Trombeta", + "ru": "Труба", + "si": null, + "sk": "Trúbka", + "sr": "труба", + "sv": "Trumpet", + "szl": null, + "tzm": null, + "uk": "Труба", + "zh_Hans": "喇叭" + } + }, + { + "number": 59, + "emoji": "🔔", + "description": "Bell", + "unicode": "U+1F514", + "translated_descriptions": { + "ar": "جَرَس", + "bg": "Звънец", + "ca": "Campana", + "cs": "Zvonek", + "de": "Glocke", + "eo": "Sonorilo", + "es": "Campana", + "et": "Kelluke", + "fi": "Soittokello", + "fr": "Cloche", + "hr": "zvono", + "hu": "Harang", + "it": "Campana", + "ja": "ベル", + "nb_NO": "Bjelle", + "nl": "Bel", + "pt_BR": "Sino", + "ru": "Колокол", + "si": null, + "sk": "Zvon", + "sr": "звоно", + "sv": "Bjällra", + "szl": null, + "tzm": null, + "uk": "Дзвін", + "zh_Hans": "铃铛" + } + }, + { + "number": 60, + "emoji": "⚓", + "description": "Anchor", + "unicode": "U+2693", + "translated_descriptions": { + "ar": "مِرسَاة", + "bg": "Котва", + "ca": "Àncora", + "cs": "Kotva", + "de": "Anker", + "eo": "Ankro", + "es": "Ancla", + "et": "Ankur", + "fi": "Ankkuri", + "fr": "Ancre", + "hr": "sidro", + "hu": "Horgony", + "it": "Ancora", + "ja": "いかり", + "nb_NO": "Anker", + "nl": "Anker", + "pt_BR": "Âncora", + "ru": "Якорь", + "si": null, + "sk": "Kotva", + "sr": "сидро", + "sv": "Ankare", + "szl": null, + "tzm": null, + "uk": "Якір", + "zh_Hans": "锚" + } + }, + { + "number": 61, + "emoji": "🎧", + "description": "Headphones", + "unicode": "U+1F3A7", + "translated_descriptions": { + "ar": "سَمّاعَة رَأس", + "bg": "Слушалки", + "ca": "Auriculars", + "cs": "Sluchátka", + "de": "Kopfhörer", + "eo": "Kapaŭdilo", + "es": "Cascos", + "et": "Kõrvaklapid", + "fi": "Kuulokkeet", + "fr": "Casque audio", + "hr": "slušalice", + "hu": "Fejhallgató", + "it": "Cuffie", + "ja": "ヘッドホン", + "nb_NO": "Hodetelefoner", + "nl": "Koptelefoon", + "pt_BR": "Fones de ouvido", + "ru": "Наушники", + "si": null, + "sk": "Slúchadlá", + "sr": "слушалице", + "sv": "Hörlurar", + "szl": null, + "tzm": null, + "uk": "Навушники", + "zh_Hans": "耳机" + } + }, + { + "number": 62, + "emoji": "📁", + "description": "Folder", + "unicode": "U+1F4C1", + "translated_descriptions": { + "ar": "مُجَلَّد", + "bg": "Папка", + "ca": "Carpeta", + "cs": "Složka", + "de": "Ordner", + "eo": "Dosierujo", + "es": "Carpeta", + "et": "Kaust", + "fi": "Kansio", + "fr": "Dossier", + "hr": "mapu", + "hu": "Mappa", + "it": "Cartella", + "ja": "フォルダ", + "nb_NO": "Mappe", + "nl": "Map", + "pt_BR": "Pasta", + "ru": "Папка", + "si": null, + "sk": "Fascikel", + "sr": "фасцикла", + "sv": "Mapp", + "szl": null, + "tzm": "Asdaw", + "uk": "Тека", + "zh_Hans": "文件夹" + } + }, + { + "number": 63, + "emoji": "📌", + "description": "Pin", + "unicode": "U+1F4CC", + "translated_descriptions": { + "ar": "دَبُّوس", + "bg": "Кабърче", + "ca": "Xinxeta", + "cs": "Špendlík", + "de": "Stecknadel", + "eo": "Pinglo", + "es": "Alfiler", + "et": "Nööpnõel", + "fi": "Nuppineula", + "fr": "Punaise", + "hr": "pribadača", + "hu": "Rajszeg", + "it": "Puntina", + "ja": "ピン", + "nb_NO": "Tegnestift", + "nl": "Duimspijker", + "pt_BR": "Alfinete", + "ru": "Булавка", + "si": null, + "sk": "Špendlík", + "sr": "чиода", + "sv": "Häftstift", + "szl": null, + "tzm": null, + "uk": "Кнопка", + "zh_Hans": "图钉" + } + } +] \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/call.ogg b/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/call.ogg new file mode 100644 index 0000000..63b5d4d Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/call.ogg differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/notification.ogg b/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/notification.ogg new file mode 100644 index 0000000..390f2bf Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/notification.ogg differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/phone.ogg b/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/phone.ogg new file mode 100644 index 0000000..7cd2864 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/assets/sounds/phone.ogg differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/fonts/MaterialIcons-Regular.otf b/appimage/Extera.AppDir/data/flutter_assets/fonts/MaterialIcons-Regular.otf new file mode 100644 index 0000000..8c99266 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/fonts/MaterialIcons-Regular.otf differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf b/appimage/Extera.AppDir/data/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf new file mode 100644 index 0000000..d580ce7 Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/flutter_map/lib/assets/flutter_map_logo.png b/appimage/Extera.AppDir/data/flutter_assets/packages/flutter_map/lib/assets/flutter_map_logo.png new file mode 100644 index 0000000..8603d0a Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/packages/flutter_map/lib/assets/flutter_map_logo.png differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/handy_window/assets/handy-window-dark.css b/appimage/Extera.AppDir/data/flutter_assets/packages/handy_window/assets/handy-window-dark.css new file mode 100644 index 0000000..a714179 --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/packages/handy_window/assets/handy-window-dark.css @@ -0,0 +1 @@ +window{background-color:#252525}window.csd.unified decoration-overlay{box-shadow:none}window.csd.unified:not(.solid-csd):not(.fullscreen):not(.maximized) decoration-overlay{box-shadow:inset 0 0 0 1px rgba(255,255,255,.07)}window.csd.unified decoration{box-shadow:0 3px 9px 1px rgba(0,0,0,.5)}window.csd.unified decoration:backdrop{box-shadow:0 3px 9px 1px rgba(0,0,0,0),0 2px 6px 2px rgba(0,0,0,.2)}headerbar{min-height:47px;background:#303030;box-shadow:inset 0 -1px rgba(0,0,0,.36);border:none}headerbar:backdrop{background:#242424}button.titlebutton{padding:4px;margin:1px} diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/handy_window/assets/handy-window.css b/appimage/Extera.AppDir/data/flutter_assets/packages/handy_window/assets/handy-window.css new file mode 100644 index 0000000..662c93c --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/packages/handy_window/assets/handy-window.css @@ -0,0 +1 @@ +window{background-color:#fff}window.csd.unified decoration-overlay{box-shadow:none}window.csd.unified:not(.solid-csd):not(.fullscreen):not(.maximized) decoration-overlay{box-shadow:inset 0 0 0 1px rgba(255,255,255,.07)}window.csd.unified decoration{box-shadow:0 3px 9px 1px rgba(0,0,0,.5)}window.csd.unified decoration:backdrop{box-shadow:0 3px 9px 1px rgba(0,0,0,0),0 2px 6px 2px rgba(0,0,0,.2)}headerbar{min-height:47px;background:#ebebeb;box-shadow:inset 0 -1px rgba(0,0,0,.07);border:none}headerbar:backdrop{background:#fafafa}button.titlebutton{padding:4px;margin:1px} diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/material/lib/fonts/material.ttf b/appimage/Extera.AppDir/data/flutter_assets/packages/material/lib/fonts/material.ttf new file mode 100644 index 0000000..84c815d Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/packages/material/lib/fonts/material.ttf differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/record_web/assets/js/record.fixwebmduration.js b/appimage/Extera.AppDir/data/flutter_assets/packages/record_web/assets/js/record.fixwebmduration.js new file mode 100644 index 0000000..dbb3cc6 --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/packages/record_web/assets/js/record.fixwebmduration.js @@ -0,0 +1,507 @@ +(function (name, definition) { + window.jsFixWebmDuration = definition(); +})('fix-webm-duration', function () { + /* + * This is the list of possible WEBM file sections by their IDs. + * Possible types: Container, Binary, Uint, Int, String, Float, Date + */ + var sections = { + 0xa45dfa3: { name: 'EBML', type: 'Container' }, + 0x286: { name: 'EBMLVersion', type: 'Uint' }, + 0x2f7: { name: 'EBMLReadVersion', type: 'Uint' }, + 0x2f2: { name: 'EBMLMaxIDLength', type: 'Uint' }, + 0x2f3: { name: 'EBMLMaxSizeLength', type: 'Uint' }, + 0x282: { name: 'DocType', type: 'String' }, + 0x287: { name: 'DocTypeVersion', type: 'Uint' }, + 0x285: { name: 'DocTypeReadVersion', type: 'Uint' }, + 0x6c: { name: 'Void', type: 'Binary' }, + 0x3f: { name: 'CRC-32', type: 'Binary' }, + 0xb538667: { name: 'SignatureSlot', type: 'Container' }, + 0x3e8a: { name: 'SignatureAlgo', type: 'Uint' }, + 0x3e9a: { name: 'SignatureHash', type: 'Uint' }, + 0x3ea5: { name: 'SignaturePublicKey', type: 'Binary' }, + 0x3eb5: { name: 'Signature', type: 'Binary' }, + 0x3e5b: { name: 'SignatureElements', type: 'Container' }, + 0x3e7b: { name: 'SignatureElementList', type: 'Container' }, + 0x2532: { name: 'SignedElement', type: 'Binary' }, + 0x8538067: { name: 'Segment', type: 'Container' }, + 0x14d9b74: { name: 'SeekHead', type: 'Container' }, + 0xdbb: { name: 'Seek', type: 'Container' }, + 0x13ab: { name: 'SeekID', type: 'Binary' }, + 0x13ac: { name: 'SeekPosition', type: 'Uint' }, + 0x549a966: { name: 'Info', type: 'Container' }, + 0x33a4: { name: 'SegmentUID', type: 'Binary' }, + 0x3384: { name: 'SegmentFilename', type: 'String' }, + 0x1cb923: { name: 'PrevUID', type: 'Binary' }, + 0x1c83ab: { name: 'PrevFilename', type: 'String' }, + 0x1eb923: { name: 'NextUID', type: 'Binary' }, + 0x1e83bb: { name: 'NextFilename', type: 'String' }, + 0x444: { name: 'SegmentFamily', type: 'Binary' }, + 0x2924: { name: 'ChapterTranslate', type: 'Container' }, + 0x29fc: { name: 'ChapterTranslateEditionUID', type: 'Uint' }, + 0x29bf: { name: 'ChapterTranslateCodec', type: 'Uint' }, + 0x29a5: { name: 'ChapterTranslateID', type: 'Binary' }, + 0xad7b1: { name: 'TimecodeScale', type: 'Uint' }, + 0x489: { name: 'Duration', type: 'Float' }, + 0x461: { name: 'DateUTC', type: 'Date' }, + 0x3ba9: { name: 'Title', type: 'String' }, + 0xd80: { name: 'MuxingApp', type: 'String' }, + 0x1741: { name: 'WritingApp', type: 'String' }, + // 0xf43b675: { name: 'Cluster', type: 'Container' }, + 0x67: { name: 'Timecode', type: 'Uint' }, + 0x1854: { name: 'SilentTracks', type: 'Container' }, + 0x18d7: { name: 'SilentTrackNumber', type: 'Uint' }, + 0x27: { name: 'Position', type: 'Uint' }, + 0x2b: { name: 'PrevSize', type: 'Uint' }, + 0x23: { name: 'SimpleBlock', type: 'Binary' }, + 0x20: { name: 'BlockGroup', type: 'Container' }, + 0x21: { name: 'Block', type: 'Binary' }, + 0x22: { name: 'BlockVirtual', type: 'Binary' }, + 0x35a1: { name: 'BlockAdditions', type: 'Container' }, + 0x26: { name: 'BlockMore', type: 'Container' }, + 0x6e: { name: 'BlockAddID', type: 'Uint' }, + 0x25: { name: 'BlockAdditional', type: 'Binary' }, + 0x1b: { name: 'BlockDuration', type: 'Uint' }, + 0x7a: { name: 'ReferencePriority', type: 'Uint' }, + 0x7b: { name: 'ReferenceBlock', type: 'Int' }, + 0x7d: { name: 'ReferenceVirtual', type: 'Int' }, + 0x24: { name: 'CodecState', type: 'Binary' }, + 0x35a2: { name: 'DiscardPadding', type: 'Int' }, + 0xe: { name: 'Slices', type: 'Container' }, + 0x68: { name: 'TimeSlice', type: 'Container' }, + 0x4c: { name: 'LaceNumber', type: 'Uint' }, + 0x4d: { name: 'FrameNumber', type: 'Uint' }, + 0x4b: { name: 'BlockAdditionID', type: 'Uint' }, + 0x4e: { name: 'Delay', type: 'Uint' }, + 0x4f: { name: 'SliceDuration', type: 'Uint' }, + 0x48: { name: 'ReferenceFrame', type: 'Container' }, + 0x49: { name: 'ReferenceOffset', type: 'Uint' }, + 0x4a: { name: 'ReferenceTimeCode', type: 'Uint' }, + 0x2f: { name: 'EncryptedBlock', type: 'Binary' }, + 0x654ae6b: { name: 'Tracks', type: 'Container' }, + 0x2e: { name: 'TrackEntry', type: 'Container' }, + 0x57: { name: 'TrackNumber', type: 'Uint' }, + 0x33c5: { name: 'TrackUID', type: 'Uint' }, + 0x3: { name: 'TrackType', type: 'Uint' }, + 0x39: { name: 'FlagEnabled', type: 'Uint' }, + 0x8: { name: 'FlagDefault', type: 'Uint' }, + 0x15aa: { name: 'FlagForced', type: 'Uint' }, + 0x1c: { name: 'FlagLacing', type: 'Uint' }, + 0x2de7: { name: 'MinCache', type: 'Uint' }, + 0x2df8: { name: 'MaxCache', type: 'Uint' }, + 0x3e383: { name: 'DefaultDuration', type: 'Uint' }, + 0x34e7a: { name: 'DefaultDecodedFieldDuration', type: 'Uint' }, + 0x3314f: { name: 'TrackTimecodeScale', type: 'Float' }, + 0x137f: { name: 'TrackOffset', type: 'Int' }, + 0x15ee: { name: 'MaxBlockAdditionID', type: 'Uint' }, + 0x136e: { name: 'Name', type: 'String' }, + 0x2b59c: { name: 'Language', type: 'String' }, + 0x6: { name: 'CodecID', type: 'String' }, + 0x23a2: { name: 'CodecPrivate', type: 'Binary' }, + 0x58688: { name: 'CodecName', type: 'String' }, + 0x3446: { name: 'AttachmentLink', type: 'Uint' }, + 0x1a9697: { name: 'CodecSettings', type: 'String' }, + 0x1b4040: { name: 'CodecInfoURL', type: 'String' }, + 0x6b240: { name: 'CodecDownloadURL', type: 'String' }, + 0x2a: { name: 'CodecDecodeAll', type: 'Uint' }, + 0x2fab: { name: 'TrackOverlay', type: 'Uint' }, + 0x16aa: { name: 'CodecDelay', type: 'Uint' }, + 0x16bb: { name: 'SeekPreRoll', type: 'Uint' }, + 0x2624: { name: 'TrackTranslate', type: 'Container' }, + 0x26fc: { name: 'TrackTranslateEditionUID', type: 'Uint' }, + 0x26bf: { name: 'TrackTranslateCodec', type: 'Uint' }, + 0x26a5: { name: 'TrackTranslateTrackID', type: 'Binary' }, + 0x60: { name: 'Video', type: 'Container' }, + 0x1a: { name: 'FlagInterlaced', type: 'Uint' }, + 0x13b8: { name: 'StereoMode', type: 'Uint' }, + 0x13c0: { name: 'AlphaMode', type: 'Uint' }, + 0x13b9: { name: 'OldStereoMode', type: 'Uint' }, + 0x30: { name: 'PixelWidth', type: 'Uint' }, + 0x3a: { name: 'PixelHeight', type: 'Uint' }, + 0x14aa: { name: 'PixelCropBottom', type: 'Uint' }, + 0x14bb: { name: 'PixelCropTop', type: 'Uint' }, + 0x14cc: { name: 'PixelCropLeft', type: 'Uint' }, + 0x14dd: { name: 'PixelCropRight', type: 'Uint' }, + 0x14b0: { name: 'DisplayWidth', type: 'Uint' }, + 0x14ba: { name: 'DisplayHeight', type: 'Uint' }, + 0x14b2: { name: 'DisplayUnit', type: 'Uint' }, + 0x14b3: { name: 'AspectRatioType', type: 'Uint' }, + 0xeb524: { name: 'ColourSpace', type: 'Binary' }, + 0xfb523: { name: 'GammaValue', type: 'Float' }, + 0x383e3: { name: 'FrameRate', type: 'Float' }, + 0x61: { name: 'Audio', type: 'Container' }, + 0x35: { name: 'SamplingFrequency', type: 'Float' }, + 0x38b5: { name: 'OutputSamplingFrequency', type: 'Float' }, + 0x1f: { name: 'Channels', type: 'Uint' }, + 0x3d7b: { name: 'ChannelPositions', type: 'Binary' }, + 0x2264: { name: 'BitDepth', type: 'Uint' }, + 0x62: { name: 'TrackOperation', type: 'Container' }, + 0x63: { name: 'TrackCombinePlanes', type: 'Container' }, + 0x64: { name: 'TrackPlane', type: 'Container' }, + 0x65: { name: 'TrackPlaneUID', type: 'Uint' }, + 0x66: { name: 'TrackPlaneType', type: 'Uint' }, + 0x69: { name: 'TrackJoinBlocks', type: 'Container' }, + 0x6d: { name: 'TrackJoinUID', type: 'Uint' }, + 0x40: { name: 'TrickTrackUID', type: 'Uint' }, + 0x41: { name: 'TrickTrackSegmentUID', type: 'Binary' }, + 0x46: { name: 'TrickTrackFlag', type: 'Uint' }, + 0x47: { name: 'TrickMasterTrackUID', type: 'Uint' }, + 0x44: { name: 'TrickMasterTrackSegmentUID', type: 'Binary' }, + 0x2d80: { name: 'ContentEncodings', type: 'Container' }, + 0x2240: { name: 'ContentEncoding', type: 'Container' }, + 0x1031: { name: 'ContentEncodingOrder', type: 'Uint' }, + 0x1032: { name: 'ContentEncodingScope', type: 'Uint' }, + 0x1033: { name: 'ContentEncodingType', type: 'Uint' }, + 0x1034: { name: 'ContentCompression', type: 'Container' }, + 0x254: { name: 'ContentCompAlgo', type: 'Uint' }, + 0x255: { name: 'ContentCompSettings', type: 'Binary' }, + 0x1035: { name: 'ContentEncryption', type: 'Container' }, + 0x7e1: { name: 'ContentEncAlgo', type: 'Uint' }, + 0x7e2: { name: 'ContentEncKeyID', type: 'Binary' }, + 0x7e3: { name: 'ContentSignature', type: 'Binary' }, + 0x7e4: { name: 'ContentSigKeyID', type: 'Binary' }, + 0x7e5: { name: 'ContentSigAlgo', type: 'Uint' }, + 0x7e6: { name: 'ContentSigHashAlgo', type: 'Uint' }, + 0xc53bb6b: { name: 'Cues', type: 'Container' }, + 0x3b: { name: 'CuePoint', type: 'Container' }, + 0x33: { name: 'CueTime', type: 'Uint' }, + 0x37: { name: 'CueTrackPositions', type: 'Container' }, + 0x77: { name: 'CueTrack', type: 'Uint' }, + 0x71: { name: 'CueClusterPosition', type: 'Uint' }, + 0x70: { name: 'CueRelativePosition', type: 'Uint' }, + 0x32: { name: 'CueDuration', type: 'Uint' }, + 0x1378: { name: 'CueBlockNumber', type: 'Uint' }, + 0x6a: { name: 'CueCodecState', type: 'Uint' }, + 0x5b: { name: 'CueReference', type: 'Container' }, + 0x16: { name: 'CueRefTime', type: 'Uint' }, + 0x17: { name: 'CueRefCluster', type: 'Uint' }, + 0x135f: { name: 'CueRefNumber', type: 'Uint' }, + 0x6b: { name: 'CueRefCodecState', type: 'Uint' }, + 0x941a469: { name: 'Attachments', type: 'Container' }, + 0x21a7: { name: 'AttachedFile', type: 'Container' }, + 0x67e: { name: 'FileDescription', type: 'String' }, + 0x66e: { name: 'FileName', type: 'String' }, + 0x660: { name: 'FileMimeType', type: 'String' }, + 0x65c: { name: 'FileData', type: 'Binary' }, + 0x6ae: { name: 'FileUID', type: 'Uint' }, + 0x675: { name: 'FileReferral', type: 'Binary' }, + 0x661: { name: 'FileUsedStartTime', type: 'Uint' }, + 0x662: { name: 'FileUsedEndTime', type: 'Uint' }, + 0x43a770: { name: 'Chapters', type: 'Container' }, + 0x5b9: { name: 'EditionEntry', type: 'Container' }, + 0x5bc: { name: 'EditionUID', type: 'Uint' }, + 0x5bd: { name: 'EditionFlagHidden', type: 'Uint' }, + 0x5db: { name: 'EditionFlagDefault', type: 'Uint' }, + 0x5dd: { name: 'EditionFlagOrdered', type: 'Uint' }, + 0x36: { name: 'ChapterAtom', type: 'Container' }, + 0x33c4: { name: 'ChapterUID', type: 'Uint' }, + 0x1654: { name: 'ChapterStringUID', type: 'String' }, + 0x11: { name: 'ChapterTimeStart', type: 'Uint' }, + 0x12: { name: 'ChapterTimeEnd', type: 'Uint' }, + 0x18: { name: 'ChapterFlagHidden', type: 'Uint' }, + 0x598: { name: 'ChapterFlagEnabled', type: 'Uint' }, + 0x2e67: { name: 'ChapterSegmentUID', type: 'Binary' }, + 0x2ebc: { name: 'ChapterSegmentEditionUID', type: 'Uint' }, + 0x23c3: { name: 'ChapterPhysicalEquiv', type: 'Uint' }, + 0xf: { name: 'ChapterTrack', type: 'Container' }, + 0x9: { name: 'ChapterTrackNumber', type: 'Uint' }, + 0x0: { name: 'ChapterDisplay', type: 'Container' }, + 0x5: { name: 'ChapString', type: 'String' }, + 0x37c: { name: 'ChapLanguage', type: 'String' }, + 0x37e: { name: 'ChapCountry', type: 'String' }, + 0x2944: { name: 'ChapProcess', type: 'Container' }, + 0x2955: { name: 'ChapProcessCodecID', type: 'Uint' }, + 0x50d: { name: 'ChapProcessPrivate', type: 'Binary' }, + 0x2911: { name: 'ChapProcessCommand', type: 'Container' }, + 0x2922: { name: 'ChapProcessTime', type: 'Uint' }, + 0x2933: { name: 'ChapProcessData', type: 'Binary' }, + 0x254c367: { name: 'Tags', type: 'Container' }, + 0x3373: { name: 'Tag', type: 'Container' }, + 0x23c0: { name: 'Targets', type: 'Container' }, + 0x28ca: { name: 'TargetTypeValue', type: 'Uint' }, + 0x23ca: { name: 'TargetType', type: 'String' }, + 0x23c5: { name: 'TagTrackUID', type: 'Uint' }, + 0x23c9: { name: 'TagEditionUID', type: 'Uint' }, + 0x23c4: { name: 'TagChapterUID', type: 'Uint' }, + 0x23c6: { name: 'TagAttachmentUID', type: 'Uint' }, + 0x27c8: { name: 'SimpleTag', type: 'Container' }, + 0x5a3: { name: 'TagName', type: 'String' }, + 0x47a: { name: 'TagLanguage', type: 'String' }, + 0x484: { name: 'TagDefault', type: 'Uint' }, + 0x487: { name: 'TagString', type: 'String' }, + 0x485: { name: 'TagBinary', type: 'Binary' } + }; + + function doInherit(newClass, baseClass) { + newClass.prototype = Object.create(baseClass.prototype); + newClass.prototype.constructor = newClass; + } + + function WebmBase(name, type) { + this.name = name || 'Unknown'; + this.type = type || 'Unknown'; + } + WebmBase.prototype.updateBySource = function () { }; + WebmBase.prototype.setSource = function (source) { + this.source = source; + this.updateBySource(); + }; + WebmBase.prototype.updateByData = function () { }; + WebmBase.prototype.setData = function (data) { + this.data = data; + this.updateByData(); + }; + + function WebmUint(name, type) { + WebmBase.call(this, name, type || 'Uint'); + } + doInherit(WebmUint, WebmBase); + function padHex(hex) { + return hex.length % 2 === 1 ? '0' + hex : hex; + } + WebmUint.prototype.updateBySource = function () { + // use hex representation of a number instead of number value + this.data = ''; + for (var i = 0; i < this.source.length; i++) { + var hex = this.source[i].toString(16); + this.data += padHex(hex); + } + }; + WebmUint.prototype.updateByData = function () { + var length = this.data.length / 2; + this.source = new Uint8Array(length); + for (var i = 0; i < length; i++) { + var hex = this.data.substr(i * 2, 2); + this.source[i] = parseInt(hex, 16); + } + }; + WebmUint.prototype.getValue = function () { + return parseInt(this.data, 16); + }; + WebmUint.prototype.setValue = function (value) { + this.setData(padHex(value.toString(16))); + }; + + function WebmFloat(name, type) { + WebmBase.call(this, name, type || 'Float'); + } + doInherit(WebmFloat, WebmBase); + WebmFloat.prototype.getFloatArrayType = function () { + return this.source && this.source.length === 4 ? Float32Array : Float64Array; + }; + WebmFloat.prototype.updateBySource = function () { + var byteArray = this.source.reverse(); + var floatArrayType = this.getFloatArrayType(); + var floatArray = new floatArrayType(byteArray.buffer); + this.data = floatArray[0]; + }; + WebmFloat.prototype.updateByData = function () { + var floatArrayType = this.getFloatArrayType(); + var floatArray = new floatArrayType([this.data]); + var byteArray = new Uint8Array(floatArray.buffer); + this.source = byteArray.reverse(); + }; + WebmFloat.prototype.getValue = function () { + return this.data; + }; + WebmFloat.prototype.setValue = function (value) { + this.setData(value); + }; + + function WebmContainer(name, type) { + WebmBase.call(this, name, type || 'Container'); + } + doInherit(WebmContainer, WebmBase); + WebmContainer.prototype.readByte = function () { + return this.source[this.offset++]; + }; + WebmContainer.prototype.readUint = function () { + var firstByte = this.readByte(); + var bytes = 8 - firstByte.toString(2).length; + var value = firstByte - (1 << (7 - bytes)); + for (var i = 0; i < bytes; i++) { + // don't use bit operators to support x86 + value *= 256; + value += this.readByte(); + } + return value; + }; + WebmContainer.prototype.updateBySource = function () { + this.data = []; + for (this.offset = 0; this.offset < this.source.length; this.offset = end) { + var id = this.readUint(); + var len = this.readUint(); + var end = Math.min(this.offset + len, this.source.length); + var data = this.source.slice(this.offset, end); + + var info = sections[id] || { name: 'Unknown', type: 'Unknown' }; + var ctr = WebmBase; + switch (info.type) { + case 'Container': + ctr = WebmContainer; + break; + case 'Uint': + ctr = WebmUint; + break; + case 'Float': + ctr = WebmFloat; + break; + } + var section = new ctr(info.name, info.type); + section.setSource(data); + this.data.push({ + id: id, + idHex: id.toString(16), + data: section + }); + } + }; + WebmContainer.prototype.writeUint = function (x, draft) { + for (var bytes = 1, flag = 0x80; x >= flag && bytes < 8; bytes++, flag *= 0x80) { } + + if (!draft) { + var value = flag + x; + for (var i = bytes - 1; i >= 0; i--) { + // don't use bit operators to support x86 + var c = value % 256; + this.source[this.offset + i] = c; + value = (value - c) / 256; + } + } + + this.offset += bytes; + }; + WebmContainer.prototype.writeSections = function (draft) { + this.offset = 0; + for (var i = 0; i < this.data.length; i++) { + var section = this.data[i], + content = section.data.source, + contentLength = content.length; + this.writeUint(section.id, draft); + this.writeUint(contentLength, draft); + if (!draft) { + this.source.set(content, this.offset); + } + this.offset += contentLength; + } + return this.offset; + }; + WebmContainer.prototype.updateByData = function () { + // run without accessing this.source to determine total length - need to know it to create Uint8Array + var length = this.writeSections('draft'); + this.source = new Uint8Array(length); + // now really write data + this.writeSections(); + }; + WebmContainer.prototype.getSectionById = function (id) { + for (var i = 0; i < this.data.length; i++) { + var section = this.data[i]; + if (section.id === id) { + return section.data; + } + } + return null; + }; + + function WebmFile(source) { + WebmContainer.call(this, 'File', 'File'); + this.setSource(source); + } + doInherit(WebmFile, WebmContainer); + WebmFile.prototype.fixDuration = function (duration, options) { + var logger = options && options.logger; + if (logger === undefined) { + logger = function (message) { + console.log(message); + }; + } else if (!logger) { + logger = function () { }; + } + + var segmentSection = this.getSectionById(0x8538067); + if (!segmentSection) { + logger('[fix-webm-duration] Segment section is missing'); + return false; + } + + var infoSection = segmentSection.getSectionById(0x549a966); + if (!infoSection) { + logger('[fix-webm-duration] Info section is missing'); + return false; + } + + var timeScaleSection = infoSection.getSectionById(0xad7b1); + if (!timeScaleSection) { + logger('[fix-webm-duration] TimecodeScale section is missing'); + return false; + } + + var durationSection = infoSection.getSectionById(0x489); + if (durationSection) { + if (durationSection.getValue() <= 0) { + logger('[fix-webm-duration] Duration section is present, but the value is empty. Applying ' + duration.toLocaleString() + ' ms.'); + durationSection.setValue(duration); + } else { + logger('[fix-webm-duration] Duration section is present'); + return false; + } + } else { + logger('[fix-webm-duration] Duration section is missing. Applying ' + duration.toLocaleString() + ' ms.'); + // append Duration section + durationSection = new WebmFloat('Duration', 'Float'); + durationSection.setValue(duration); + infoSection.data.push({ + id: 0x489, + data: durationSection + }); + } + + // set default time scale to 1 millisecond (1000000 nanoseconds) + timeScaleSection.setValue(1000000); + infoSection.updateByData(); + segmentSection.updateByData(); + this.updateByData(); + + return true; + }; + WebmFile.prototype.toBlob = function (mimeType) { + return new Blob([this.source.buffer], { type: mimeType || 'audio/webm' }); + }; + + function fixWebmDuration(blob, duration, callback, options) { + // The callback may be omitted - then the third argument is options + if (typeof callback === "object") { + options = callback; + callback = undefined; + } + + if (!callback) { + return new Promise(function (resolve) { + fixWebmDuration(blob, duration, resolve, options); + }); + } + + try { + var reader = new FileReader(); + reader.onloadend = function () { + try { + var file = new WebmFile(new Uint8Array(reader.result)); + if (file.fixDuration(duration, options)) { + blob = file.toBlob(blob.type); + } + } catch (ex) { + // ignore + } + callback(blob); + }; + reader.readAsArrayBuffer(blob); + } catch (ex) { + callback(blob); + } + } + + // Support AMD import default + fixWebmDuration.default = fixWebmDuration; + + return fixWebmDuration; +}); diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/record_web/assets/js/record.worklet.js b/appimage/Extera.AppDir/data/flutter_assets/packages/record_web/assets/js/record.worklet.js new file mode 100644 index 0000000..90952fc --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/packages/record_web/assets/js/record.worklet.js @@ -0,0 +1,400 @@ +class RecorderProcessor extends AudioWorkletProcessor { + static get parameterDescriptors() { + return [ + { + name: 'numChannels', + defaultValue: 1, + minValue: 1, + maxValue: 16 + }, + { + name: 'sampleRate', + defaultValue: 48000, + minValue: 8000, + maxValue: 96000 + } + ]; + } + + // Buffer size compromise between size and process call frequency + _bufferSize = 4096 + // The current buffer fill level + _bytesWritten = 0 + // Buffer per channel + _buffers = [] + // Resampler (passthrough, down or up) + _resampler = null + // Config + _numChannels = 1 + _sampleRate = 48000 + + constructor(options) { + super(options) + + this._numChannels = options.parameterData.numChannels + this._sampleRate = options.parameterData.sampleRate + + // Resampler(current context sample rate, desired sample rate, num channels, buffer size) + // num channels is always 1 since we resample after interleaving channels + this._resampler = new Resampler(sampleRate, this._sampleRate, 1, this._bufferSize * this._numChannels) + + this.initBuffers() + } + + initBuffers() { + this._bytesWritten = 0 + this._buffers = [] + + for (let channel = 0; channel < this._numChannels; channel++) { + this._buffers[channel] = [] + } + } + + /** + * @returns {boolean} + */ + isBufferEmpty() { + return this._bytesWritten === 0 + } + + /** + * @returns {boolean} + */ + isBufferFull() { + return this._bytesWritten >= this._bufferSize + } + + /** + * @param {Float32Array[][]} inputs + * @returns {boolean} + */ + process(inputs) { + if (this.isBufferFull()) { + this.flush() + } + + const input = inputs[0] + + if (input.length == 0) { + // Sometimes, Firefox doesn't give any input. Skip this frame to not fail. + return true + } + + for (let channel = 0; channel < this._numChannels; channel++) { + // Push a copy of the array. + // The underlying implementation may reuse it which will break the recording. + this._buffers[channel].push([...input[channel]]) + } + + this._bytesWritten += input[0].length + + return true + } + + flush() { + let channels = [] + for (let channel = 0; channel < this._numChannels; channel++) { + channels.push(this.mergeFloat32Arrays(this._buffers[channel], this._bytesWritten)) + } + + let interleaved = this.interleave(channels) + + let resampled = this._resampler.resample(interleaved) + + this.port.postMessage(this.floatTo16BitPCM(resampled)) + + this.initBuffers() + } + + mergeFloat32Arrays(arrays, bytesWritten) { + let result = new Float32Array(bytesWritten) + var offset = 0 + + for (let i = 0; i < arrays.length; i++) { + result.set(arrays[i], offset) + offset += arrays[i].length + } + + return result + } + + // Interleave data from channels from LLLLRRRR to LRLRLRLR + interleave(channels) { + if (channels === 1) { + return channels[0] + } + + var length = 0 + for (let i = 0; i < channels.length; i++) { + length += channels[i].length + } + + let result = new Float32Array(length) + + var index = 0 + var inputIndex = 0 + + while (index < length) { + for (let i = 0; i < channels.length; i++) { + result[index] = channels[i][inputIndex] + index++ + } + + inputIndex++ + } + + return result + } + + floatTo16BitPCM(input) { + let output = new DataView(new ArrayBuffer(input.length * 2)) + + for (let i = 0; i < input.length; i++) { + let s = Math.max(-1, Math.min(1, input[i])) + let s16 = s < 0 ? s * 0x8000 : s * 0x7FFF + output.setInt16(i * 2, s16, true) + } + + return new Int16Array(output.buffer) + } +} + +class Resampler { + constructor(fromSampleRate, toSampleRate, channels, inputBufferSize) { + + if (!fromSampleRate || !toSampleRate || !channels) { + throw (new Error("Invalid settings specified for the resampler.")); + } + this.resampler = null; + this.fromSampleRate = fromSampleRate; + this.toSampleRate = toSampleRate; + this.channels = channels || 0; + this.inputBufferSize = inputBufferSize; + this.initialize() + } + + initialize() { + if (this.fromSampleRate == this.toSampleRate) { + + // Setup resampler bypass - Resampler just returns what was passed through + this.resampler = (buffer) => { + return buffer + }; + this.ratioWeight = 1; + + } else { + if (this.fromSampleRate < this.toSampleRate) { + + // Use generic linear interpolation if upsampling, + // as linear interpolation produces a gradient that we want + // and works fine with two input sample points per output in this case. + this.linearInterpolation(); + this.lastWeight = 1; + + } else { + + // Custom resampler I wrote that doesn't skip samples + // like standard linear interpolation in high downsampling. + // This is more accurate than linear interpolation on downsampling. + this.multiTap(); + this.tailExists = false; + this.lastWeight = 0; + } + + // Initialize the internal buffer: + this.initializeBuffers(); + this.ratioWeight = this.fromSampleRate / this.toSampleRate; + } + } + + bufferSlice(sliceAmount) { + + //Typed array and normal array buffer section referencing: + try { + return this.outputBuffer.subarray(0, sliceAmount); + } + catch (error) { + try { + //Regular array pass: + this.outputBuffer.length = sliceAmount; + return this.outputBuffer; + } + catch (error) { + //Nightly Firefox 4 used to have the subarray function named as slice: + return this.outputBuffer.slice(0, sliceAmount); + } + } + } + + initializeBuffers() { + this.outputBufferSize = (Math.ceil(this.inputBufferSize * this.toSampleRate / this.fromSampleRate / this.channels * 1.000000476837158203125) + this.channels) + this.channels; + try { + this.outputBuffer = new Float32Array(this.outputBufferSize); + this.lastOutput = new Float32Array(this.channels); + } + catch (error) { + this.outputBuffer = []; + this.lastOutput = []; + } + } + + linearInterpolation() { + this.resampler = (buffer) => { + let bufferLength = buffer.length, + channels = this.channels, + outLength, + ratioWeight, + weight, + firstWeight, + secondWeight, + sourceOffset, + outputOffset, + outputBuffer, + channel; + + if ((bufferLength % channels) !== 0) { + throw (new Error("Buffer was of incorrect sample length.")); + } + if (bufferLength <= 0) { + return []; + } + + outLength = this.outputBufferSize; + ratioWeight = this.ratioWeight; + weight = this.lastWeight; + firstWeight = 0; + secondWeight = 0; + sourceOffset = 0; + outputOffset = 0; + outputBuffer = this.outputBuffer; + + for (; weight < 1; weight += ratioWeight) { + secondWeight = weight % 1; + firstWeight = 1 - secondWeight; + this.lastWeight = weight % 1; + for (channel = 0; channel < this.channels; ++channel) { + outputBuffer[outputOffset++] = (this.lastOutput[channel] * firstWeight) + (buffer[channel] * secondWeight); + } + } + weight -= 1; + for (bufferLength -= channels, sourceOffset = Math.floor(weight) * channels; outputOffset < outLength && sourceOffset < bufferLength;) { + secondWeight = weight % 1; + firstWeight = 1 - secondWeight; + for (channel = 0; channel < this.channels; ++channel) { + outputBuffer[outputOffset++] = (buffer[sourceOffset + ((channel > 0) ? (channel) : 0)] * firstWeight) + (buffer[sourceOffset + (channels + channel)] * secondWeight); + } + weight += ratioWeight; + sourceOffset = Math.floor(weight) * channels; + } + for (channel = 0; channel < channels; ++channel) { + this.lastOutput[channel] = buffer[sourceOffset++]; + } + return this.bufferSlice(outputOffset); + }; + } + + multiTap() { + this.resampler = (buffer) => { + let bufferLength = buffer.length, + outLength, + output_variable_list, + channels = this.channels, + ratioWeight, + weight, + channel, + actualPosition, + amountToNext, + alreadyProcessedTail, + outputBuffer, + outputOffset, + currentPosition; + + if ((bufferLength % channels) !== 0) { + throw (new Error("Buffer was of incorrect sample length.")); + } + if (bufferLength <= 0) { + return []; + } + + outLength = this.outputBufferSize; + output_variable_list = []; + ratioWeight = this.ratioWeight; + weight = 0; + actualPosition = 0; + amountToNext = 0; + alreadyProcessedTail = !this.tailExists; + this.tailExists = false; + outputBuffer = this.outputBuffer; + outputOffset = 0; + currentPosition = 0; + + for (channel = 0; channel < channels; ++channel) { + output_variable_list[channel] = 0; + } + + do { + if (alreadyProcessedTail) { + weight = ratioWeight; + for (channel = 0; channel < channels; ++channel) { + output_variable_list[channel] = 0; + } + } else { + weight = this.lastWeight; + for (channel = 0; channel < channels; ++channel) { + output_variable_list[channel] = this.lastOutput[channel]; + } + alreadyProcessedTail = true; + } + while (weight > 0 && actualPosition < bufferLength) { + amountToNext = 1 + actualPosition - currentPosition; + if (weight >= amountToNext) { + for (channel = 0; channel < channels; ++channel) { + output_variable_list[channel] += buffer[actualPosition++] * amountToNext; + } + currentPosition = actualPosition; + weight -= amountToNext; + } else { + for (channel = 0; channel < channels; ++channel) { + output_variable_list[channel] += buffer[actualPosition + ((channel > 0) ? channel : 0)] * weight; + } + currentPosition += weight; + weight = 0; + break; + } + } + + if (weight === 0) { + for (channel = 0; channel < channels; ++channel) { + outputBuffer[outputOffset++] = output_variable_list[channel] / ratioWeight; + } + } else { + this.lastWeight = weight; + for (channel = 0; channel < channels; ++channel) { + this.lastOutput[channel] = output_variable_list[channel]; + } + this.tailExists = true; + break; + } + } while (actualPosition < bufferLength && outputOffset < outLength); + return this.bufferSlice(outputOffset); + }; + } + + resample(buffer) { + if (this.fromSampleRate == this.toSampleRate) { + this.ratioWeight = 1; + } else { + if (this.fromSampleRate < this.toSampleRate) { + this.lastWeight = 1; + } else { + this.tailExists = false; + this.lastWeight = 0; + } + this.initializeBuffers(); + this.ratioWeight = this.fromSampleRate / this.toSampleRate; + } + return this.resampler(buffer) + } +} + +registerProcessor("recorder.worklet", RecorderProcessor) \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/flutter_assets/packages/wakelock_plus/assets/no_sleep.js b/appimage/Extera.AppDir/data/flutter_assets/packages/wakelock_plus/assets/no_sleep.js new file mode 100644 index 0000000..ccfab74 --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/packages/wakelock_plus/assets/no_sleep.js @@ -0,0 +1,230 @@ +var webm = + 'data:video/webm;base64,GkXfo0AgQoaBAUL3gQFC8oEEQvOBCEKCQAR3ZWJtQoeBAkKFgQIYU4BnQI0VSalmQCgq17FAAw9CQE2AQAZ3aGFtbXlXQUAGd2hhbW15RIlACECPQAAAAAAAFlSua0AxrkAu14EBY8WBAZyBACK1nEADdW5khkAFVl9WUDglhohAA1ZQOIOBAeBABrCBCLqBCB9DtnVAIueBAKNAHIEAAIAwAQCdASoIAAgAAUAmJaQAA3AA/vz0AAA=' +var mp4 = + 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA=' + +var _createClass = (function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i] + descriptor.enumerable = descriptor.enumerable || false + descriptor.configurable = true + if ('value' in descriptor) descriptor.writable = true + Object.defineProperty(target, descriptor.key, descriptor) + } + } + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps) + if (staticProps) defineProperties(Constructor, staticProps) + return Constructor + } +})() + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError('Cannot call a class as a function') + } +} + +// Detect iOS browsers < version 10 +var oldIOS = + typeof navigator !== 'undefined' && + parseFloat( + ( + '' + + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec( + navigator.userAgent + ) || [0, ''])[1] + ) + .replace('undefined', '3_2') + .replace('_', '.') + .replace('_', '') + ) < 10 && + !window.MSStream + +// Detect native Wake Lock API support +var nativeWakeLock = 'wakeLock' in navigator + +var NoSleep = (function () { + var _releasedNative = true + var _nativeRequestInProgress = false + + function NoSleep() { + var _this = this + + _classCallCheck(this, NoSleep) + + if (nativeWakeLock) { + this._wakeLock = null + var handleVisibilityChange = function handleVisibilityChange() { + if ( + _this._wakeLock !== null && + document.visibilityState === 'visible' + ) { + _this.enable() + } + } + document.addEventListener('visibilitychange', handleVisibilityChange) + document.addEventListener('fullscreenchange', handleVisibilityChange) + } else if (oldIOS) { + this.noSleepTimer = null + } else { + // Set up no sleep video element + this.noSleepVideo = document.createElement('video') + + this.noSleepVideo.setAttribute('title', 'No Sleep') + this.noSleepVideo.setAttribute('playsinline', '') + + this._addSourceToVideo(this.noSleepVideo, 'webm', webm) + this._addSourceToVideo(this.noSleepVideo, 'mp4', mp4) + + this.noSleepVideo.addEventListener('loadedmetadata', function () { + if (_this.noSleepVideo.duration <= 1) { + // webm source + _this.noSleepVideo.setAttribute('loop', '') + } else { + // mp4 source + _this.noSleepVideo.addEventListener('timeupdate', function () { + if (_this.noSleepVideo.currentTime > 0.5) { + _this.noSleepVideo.currentTime = Math.random() + } + }) + } + }) + } + } + + _createClass(NoSleep, [ + { + key: '_addSourceToVideo', + value: function _addSourceToVideo(element, type, dataURI) { + var source = document.createElement('source') + source.src = dataURI + source.type = 'video/' + type + element.appendChild(source) + }, + }, + { + key: 'enable', + value: function enable() { + var _this2 = this + + if (nativeWakeLock) { + _nativeRequestInProgress = true + navigator.wakeLock + .request('screen') + .then(function (wakeLock) { + _releasedNative = false + _nativeRequestInProgress = false + + _this2._wakeLock = wakeLock + _this2._wakeLock.addEventListener('release', function () { + _releasedNative = true + _this2._wakeLock = null + }) + }) + .catch(function (err) { + _nativeRequestInProgress = false + console.error(err.name + ', ' + err.message) + }) + } else if (oldIOS) { + this.disable() + console.warn( + '\n NoSleep enabled for older iOS devices. This can interrupt\n active or long-running network requests from completing successfully.\n See https://github.com/richtr/NoSleep.js/issues/15 for more details.\n ' + ) + this.noSleepTimer = window.setInterval(function () { + if (!document.hidden) { + window.location.href = window.location.href.split('#')[0] + window.setTimeout(window.stop, 0) + } + }, 15000) + } else { + this.noSleepVideo.play() + } + }, + }, + { + key: 'disable', + value: function disable() { + if (nativeWakeLock) { + if (this._wakeLock != null) { + _releasedNative = true + this._wakeLock.release() + } + + this._wakeLock = null + } else if (oldIOS) { + if (this.noSleepTimer) { + console.warn( + '\n NoSleep now disabled for older iOS devices.\n ' + ) + window.clearInterval(this.noSleepTimer) + this.noSleepTimer = null + } + } else { + this.noSleepVideo.pause() + } + }, + }, + { + key: 'enabled', + value: async function enabled() { + if (nativeWakeLock) { + if (_nativeRequestInProgress == true) { + // Wait until the request is done. + while (true) { + // Wait for 42 milliseconds. + await new Promise((resolve, reject) => setTimeout(resolve, 42)) + if (_nativeRequestInProgress == false) { + break + } + } + } + + // todo: use WakeLockSentinel.released when that is available (https://developer.mozilla.org/en-US/docs/Web/API/WakeLockSentinel/released) + if (_releasedNative != false) { + return false + } + + return true + } else if (oldIOS) { + return this.noSleepTimer != null + } else { + if (this.noSleepVideo == undefined) { + return false + } + + return !this.noSleepVideo.paused + } + }, + }, + ]) + + return NoSleep +})() + +var noSleep = new NoSleep() + +var Wakelock = { + enabled: async function () { + try { + return noSleep.enabled() + } catch (e) { + return false + } + }, + toggle: async function (enable) { + if (enable) { + noSleep.enable() + } else { + noSleep.disable() + } + }, +} + +if (nativeWakeLock != true) { + // The first non-native call sometimes throws an error, however, + // the error does not leak the try-catch above. Therefore, this + // is an easy fix that realiably works. + Wakelock.enabled() +} diff --git a/appimage/Extera.AppDir/data/flutter_assets/shaders/ink_sparkle.frag b/appimage/Extera.AppDir/data/flutter_assets/shaders/ink_sparkle.frag new file mode 100644 index 0000000..5c91a6c Binary files /dev/null and b/appimage/Extera.AppDir/data/flutter_assets/shaders/ink_sparkle.frag differ diff --git a/appimage/Extera.AppDir/data/flutter_assets/version.json b/appimage/Extera.AppDir/data/flutter_assets/version.json new file mode 100644 index 0000000..eacb670 --- /dev/null +++ b/appimage/Extera.AppDir/data/flutter_assets/version.json @@ -0,0 +1 @@ +{"app_name":"extera_next","version":"2.0.0","package_name":"extera_next"} \ No newline at end of file diff --git a/appimage/Extera.AppDir/data/icudtl.dat b/appimage/Extera.AppDir/data/icudtl.dat new file mode 100644 index 0000000..17e5b2a Binary files /dev/null and b/appimage/Extera.AppDir/data/icudtl.dat differ diff --git a/appimage/Extera.AppDir/extera.svg b/appimage/Extera.AppDir/extera.svg new file mode 100644 index 0000000..767a86a --- /dev/null +++ b/appimage/Extera.AppDir/extera.svg @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/appimage/Extera.AppDir/extera_next b/appimage/Extera.AppDir/extera_next new file mode 100755 index 0000000..fcc8c70 Binary files /dev/null and b/appimage/Extera.AppDir/extera_next differ diff --git a/appimage/Extera.AppDir/lib/libapp.so b/appimage/Extera.AppDir/lib/libapp.so new file mode 100644 index 0000000..046d4c3 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libapp.so differ diff --git a/appimage/Extera.AppDir/lib/libdesktop_drop_plugin.so b/appimage/Extera.AppDir/lib/libdesktop_drop_plugin.so new file mode 100644 index 0000000..0cfdc62 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libdesktop_drop_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libdynamic_color_plugin.so b/appimage/Extera.AppDir/lib/libdynamic_color_plugin.so new file mode 100644 index 0000000..0fd22d8 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libdynamic_color_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libemoji_picker_flutter_plugin.so b/appimage/Extera.AppDir/lib/libemoji_picker_flutter_plugin.so new file mode 100644 index 0000000..bebd365 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libemoji_picker_flutter_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libfile_selector_linux_plugin.so b/appimage/Extera.AppDir/lib/libfile_selector_linux_plugin.so new file mode 100644 index 0000000..5e78878 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libfile_selector_linux_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libflutter_linux_gtk.so b/appimage/Extera.AppDir/lib/libflutter_linux_gtk.so new file mode 100644 index 0000000..f6023c4 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libflutter_linux_gtk.so differ diff --git a/appimage/Extera.AppDir/lib/libflutter_secure_storage_linux_plugin.so b/appimage/Extera.AppDir/lib/libflutter_secure_storage_linux_plugin.so new file mode 100644 index 0000000..4759d19 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libflutter_secure_storage_linux_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libflutter_webrtc_plugin.so b/appimage/Extera.AppDir/lib/libflutter_webrtc_plugin.so new file mode 100644 index 0000000..0135e10 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libflutter_webrtc_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libgtk_plugin.so b/appimage/Extera.AppDir/lib/libgtk_plugin.so new file mode 100644 index 0000000..da9a983 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libgtk_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libhandy_flutter.so b/appimage/Extera.AppDir/lib/libhandy_flutter.so new file mode 100644 index 0000000..e783d91 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libhandy_flutter.so differ diff --git a/appimage/Extera.AppDir/lib/libhandy_window_plugin.so b/appimage/Extera.AppDir/lib/libhandy_window_plugin.so new file mode 100644 index 0000000..d20758a Binary files /dev/null and b/appimage/Extera.AppDir/lib/libhandy_window_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libpasteboard_plugin.so b/appimage/Extera.AppDir/lib/libpasteboard_plugin.so new file mode 100644 index 0000000..7f9781a Binary files /dev/null and b/appimage/Extera.AppDir/lib/libpasteboard_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/librecord_linux_plugin.so b/appimage/Extera.AppDir/lib/librecord_linux_plugin.so new file mode 100644 index 0000000..c1e1ee2 Binary files /dev/null and b/appimage/Extera.AppDir/lib/librecord_linux_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libsqlcipher_flutter_libs_plugin.so b/appimage/Extera.AppDir/lib/libsqlcipher_flutter_libs_plugin.so new file mode 100644 index 0000000..a01f2e4 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libsqlcipher_flutter_libs_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/liburl_launcher_linux_plugin.so b/appimage/Extera.AppDir/lib/liburl_launcher_linux_plugin.so new file mode 100644 index 0000000..7137a19 Binary files /dev/null and b/appimage/Extera.AppDir/lib/liburl_launcher_linux_plugin.so differ diff --git a/appimage/Extera.AppDir/lib/libvodozemac_bindings_dart.so b/appimage/Extera.AppDir/lib/libvodozemac_bindings_dart.so new file mode 100644 index 0000000..904fb01 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libvodozemac_bindings_dart.so differ diff --git a/appimage/Extera.AppDir/lib/libwebrtc.so b/appimage/Extera.AppDir/lib/libwebrtc.so new file mode 100644 index 0000000..08ce7d1 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libwebrtc.so differ diff --git a/appimage/Extera.AppDir/lib/libwindow_to_front_plugin.so b/appimage/Extera.AppDir/lib/libwindow_to_front_plugin.so new file mode 100644 index 0000000..f535034 Binary files /dev/null and b/appimage/Extera.AppDir/lib/libwindow_to_front_plugin.so differ diff --git a/appimage/Extera.desktop b/appimage/Extera.desktop new file mode 100644 index 0000000..81cabe1 --- /dev/null +++ b/appimage/Extera.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Extera Next +Comment=Matrix Client. Chat with your friends +Exec=AppRun +Icon=extera +Terminal=false +Categories=Network;Chat;InstantMessaging;X-Matrix; diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index dd1d0e9..79f1edb 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -2,6 +2,10 @@ "@@locale": "en", "@@last_modified": "2025-06-05 12:38:37.885451", "noSendPermission": "You can't send messages here", + "noMessagesYet": "No messages yet", + "longPressToRecordVoiceMessage": "Long press to record voice message.", + "pause": "Pause", + "resume": "Resume", "@noSendPermission": {}, "alwaysUse24HourFormat": "false", "@alwaysUse24HourFormat": { diff --git a/assets/l10n/intl_ru.arb b/assets/l10n/intl_ru.arb index cf6c6b5..200e428 100644 --- a/assets/l10n/intl_ru.arb +++ b/assets/l10n/intl_ru.arb @@ -3,6 +3,10 @@ "@@last_modified": "2021-08-14 12:41:09.903021", "noSendPermission": "Вы не можете отправлять сообщения", "@noSendPermission": {}, + "noMessagesYet": "Нет сообщений", + "longPressToRecordVoiceMessage": "Зажмите, чтобы записать голосовое сообщение.", + "pause": "Пауза", + "resume": "Продолжить", "alwaysUse24HourFormat": "нет", "@alwaysUse24HourFormat": { "description": "Set to true to always display time of day in 24 hour format." diff --git a/lib/config/themes.dart b/lib/config/themes.dart index 5b04925..4e1958a 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -40,7 +40,7 @@ abstract class FluffyThemes { BuildContext context, Brightness brightness, [ Color? seed, - bool? pureBlack, + bool? pureBlack, ]) { final extraDarkColors = (brightness == Brightness.dark && pureBlack == true) ? { @@ -79,6 +79,7 @@ abstract class FluffyThemes { useMaterial3: true, brightness: brightness, colorScheme: colorScheme, + useSystemColors: true, dividerColor: brightness == Brightness.dark ? colorScheme.surfaceContainerHighest : colorScheme.surfaceContainer, @@ -117,6 +118,8 @@ abstract class FluffyThemes { isColumnMode ? colorScheme.surfaceContainer.withAlpha(128) : null, surfaceTintColor: isColumnMode ? colorScheme.surface : null, backgroundColor: isColumnMode ? colorScheme.surface : null, + actionsPadding: + isColumnMode ? const EdgeInsets.symmetric(horizontal: 16.0) : null, systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: brightness.reversed, @@ -139,6 +142,7 @@ abstract class FluffyThemes { ), snackBarTheme: isColumnMode ? const SnackBarThemeData( + showCloseIcon: true, behavior: SnackBarBehavior.floating, width: FluffyThemes.columnWidth * 1.5, ) diff --git a/lib/generated/l10n/l10n.dart b/lib/generated/l10n/l10n.dart index 177afcf..f6273e2 100644 --- a/lib/generated/l10n/l10n.dart +++ b/lib/generated/l10n/l10n.dart @@ -199,6 +199,30 @@ abstract class L10n { /// **'You can\'t send messages here'** String get noSendPermission; + /// No description provided for @noMessagesYet. + /// + /// In en, this message translates to: + /// **'No messages yet'** + String get noMessagesYet; + + /// No description provided for @longPressToRecordVoiceMessage. + /// + /// In en, this message translates to: + /// **'Long press to record voice message.'** + String get longPressToRecordVoiceMessage; + + /// No description provided for @pause. + /// + /// In en, this message translates to: + /// **'Pause'** + String get pause; + + /// No description provided for @resume. + /// + /// In en, this message translates to: + /// **'Resume'** + String get resume; + /// Set to true to always display time of day in 24 hour format. /// /// In en, this message translates to: diff --git a/lib/generated/l10n/l10n_ar.dart b/lib/generated/l10n/l10n_ar.dart index 7d24b3f..1ed8657 100644 --- a/lib/generated/l10n/l10n_ar.dart +++ b/lib/generated/l10n/l10n_ar.dart @@ -11,6 +11,19 @@ class L10nAr extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_be.dart b/lib/generated/l10n/l10n_be.dart index e21f337..093df27 100644 --- a/lib/generated/l10n/l10n_be.dart +++ b/lib/generated/l10n/l10n_be.dart @@ -11,6 +11,19 @@ class L10nBe extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_bn.dart b/lib/generated/l10n/l10n_bn.dart index 5e23af8..2158fe0 100644 --- a/lib/generated/l10n/l10n_bn.dart +++ b/lib/generated/l10n/l10n_bn.dart @@ -11,6 +11,19 @@ class L10nBn extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_bo.dart b/lib/generated/l10n/l10n_bo.dart index 02f7c7f..50241ed 100644 --- a/lib/generated/l10n/l10n_bo.dart +++ b/lib/generated/l10n/l10n_bo.dart @@ -11,6 +11,19 @@ class L10nBo extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_ca.dart b/lib/generated/l10n/l10n_ca.dart index 05a1467..9d2a928 100644 --- a/lib/generated/l10n/l10n_ca.dart +++ b/lib/generated/l10n/l10n_ca.dart @@ -11,6 +11,19 @@ class L10nCa extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'true'; diff --git a/lib/generated/l10n/l10n_cs.dart b/lib/generated/l10n/l10n_cs.dart index 1ea1f9f..c676546 100644 --- a/lib/generated/l10n/l10n_cs.dart +++ b/lib/generated/l10n/l10n_cs.dart @@ -11,6 +11,19 @@ class L10nCs extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'Vypnuto'; diff --git a/lib/generated/l10n/l10n_de.dart b/lib/generated/l10n/l10n_de.dart index b6223f0..31fb3b2 100644 --- a/lib/generated/l10n/l10n_de.dart +++ b/lib/generated/l10n/l10n_de.dart @@ -11,6 +11,19 @@ class L10nDe extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'true'; diff --git a/lib/generated/l10n/l10n_el.dart b/lib/generated/l10n/l10n_el.dart index 95eb3bb..3dda57c 100644 --- a/lib/generated/l10n/l10n_el.dart +++ b/lib/generated/l10n/l10n_el.dart @@ -11,6 +11,19 @@ class L10nEl extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_en.dart b/lib/generated/l10n/l10n_en.dart index cf2149e..c770e14 100644 --- a/lib/generated/l10n/l10n_en.dart +++ b/lib/generated/l10n/l10n_en.dart @@ -11,6 +11,19 @@ class L10nEn extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_eo.dart b/lib/generated/l10n/l10n_eo.dart index bb863ae..750e963 100644 --- a/lib/generated/l10n/l10n_eo.dart +++ b/lib/generated/l10n/l10n_eo.dart @@ -11,6 +11,19 @@ class L10nEo extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_es.dart b/lib/generated/l10n/l10n_es.dart index 7b57496..34187da 100644 --- a/lib/generated/l10n/l10n_es.dart +++ b/lib/generated/l10n/l10n_es.dart @@ -11,6 +11,19 @@ class L10nEs extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'falso'; diff --git a/lib/generated/l10n/l10n_et.dart b/lib/generated/l10n/l10n_et.dart index 6933dc2..152294c 100644 --- a/lib/generated/l10n/l10n_et.dart +++ b/lib/generated/l10n/l10n_et.dart @@ -11,6 +11,19 @@ class L10nEt extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_eu.dart b/lib/generated/l10n/l10n_eu.dart index 406530e..25fb72a 100644 --- a/lib/generated/l10n/l10n_eu.dart +++ b/lib/generated/l10n/l10n_eu.dart @@ -11,6 +11,19 @@ class L10nEu extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_fa.dart b/lib/generated/l10n/l10n_fa.dart index 8b104a6..e4da45e 100644 --- a/lib/generated/l10n/l10n_fa.dart +++ b/lib/generated/l10n/l10n_fa.dart @@ -11,6 +11,19 @@ class L10nFa extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_fi.dart b/lib/generated/l10n/l10n_fi.dart index 7c6e930..22d0e7e 100644 --- a/lib/generated/l10n/l10n_fi.dart +++ b/lib/generated/l10n/l10n_fi.dart @@ -11,6 +11,19 @@ class L10nFi extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_fil.dart b/lib/generated/l10n/l10n_fil.dart index 4964f98..1e61fcc 100644 --- a/lib/generated/l10n/l10n_fil.dart +++ b/lib/generated/l10n/l10n_fil.dart @@ -11,6 +11,19 @@ class L10nFil extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_fr.dart b/lib/generated/l10n/l10n_fr.dart index c79483f..7e872bc 100644 --- a/lib/generated/l10n/l10n_fr.dart +++ b/lib/generated/l10n/l10n_fr.dart @@ -11,6 +11,19 @@ class L10nFr extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'true'; diff --git a/lib/generated/l10n/l10n_ga.dart b/lib/generated/l10n/l10n_ga.dart index 5bb6f92..c204f86 100644 --- a/lib/generated/l10n/l10n_ga.dart +++ b/lib/generated/l10n/l10n_ga.dart @@ -11,6 +11,19 @@ class L10nGa extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'bréagach'; diff --git a/lib/generated/l10n/l10n_gl.dart b/lib/generated/l10n/l10n_gl.dart index 3b68412..9539583 100644 --- a/lib/generated/l10n/l10n_gl.dart +++ b/lib/generated/l10n/l10n_gl.dart @@ -11,6 +11,19 @@ class L10nGl extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'falso'; diff --git a/lib/generated/l10n/l10n_he.dart b/lib/generated/l10n/l10n_he.dart index 82de3e2..8ef9c05 100644 --- a/lib/generated/l10n/l10n_he.dart +++ b/lib/generated/l10n/l10n_he.dart @@ -11,6 +11,19 @@ class L10nHe extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_hi.dart b/lib/generated/l10n/l10n_hi.dart index e03e332..e3ef5b0 100644 --- a/lib/generated/l10n/l10n_hi.dart +++ b/lib/generated/l10n/l10n_hi.dart @@ -11,6 +11,19 @@ class L10nHi extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_hr.dart b/lib/generated/l10n/l10n_hr.dart index e8fdae4..2f4fa52 100644 --- a/lib/generated/l10n/l10n_hr.dart +++ b/lib/generated/l10n/l10n_hr.dart @@ -11,6 +11,19 @@ class L10nHr extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'true'; diff --git a/lib/generated/l10n/l10n_hu.dart b/lib/generated/l10n/l10n_hu.dart index 567d2e3..51d1308 100644 --- a/lib/generated/l10n/l10n_hu.dart +++ b/lib/generated/l10n/l10n_hu.dart @@ -11,6 +11,19 @@ class L10nHu extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'true'; diff --git a/lib/generated/l10n/l10n_ia.dart b/lib/generated/l10n/l10n_ia.dart index 821f1c8..5530db0 100644 --- a/lib/generated/l10n/l10n_ia.dart +++ b/lib/generated/l10n/l10n_ia.dart @@ -11,6 +11,19 @@ class L10nIa extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_id.dart b/lib/generated/l10n/l10n_id.dart index 8114e83..c8f5597 100644 --- a/lib/generated/l10n/l10n_id.dart +++ b/lib/generated/l10n/l10n_id.dart @@ -11,6 +11,19 @@ class L10nId extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'tidak'; diff --git a/lib/generated/l10n/l10n_ie.dart b/lib/generated/l10n/l10n_ie.dart index ac81d87..41c387a 100644 --- a/lib/generated/l10n/l10n_ie.dart +++ b/lib/generated/l10n/l10n_ie.dart @@ -11,6 +11,19 @@ class L10nIe extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_it.dart b/lib/generated/l10n/l10n_it.dart index f0f87b2..f85665a 100644 --- a/lib/generated/l10n/l10n_it.dart +++ b/lib/generated/l10n/l10n_it.dart @@ -11,6 +11,19 @@ class L10nIt extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'disattivato'; diff --git a/lib/generated/l10n/l10n_ja.dart b/lib/generated/l10n/l10n_ja.dart index b88e20e..9ac82ab 100644 --- a/lib/generated/l10n/l10n_ja.dart +++ b/lib/generated/l10n/l10n_ja.dart @@ -11,6 +11,19 @@ class L10nJa extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_ka.dart b/lib/generated/l10n/l10n_ka.dart index 5468e69..fc04f1a 100644 --- a/lib/generated/l10n/l10n_ka.dart +++ b/lib/generated/l10n/l10n_ka.dart @@ -11,6 +11,19 @@ class L10nKa extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_ko.dart b/lib/generated/l10n/l10n_ko.dart index 395e99a..c0f7426 100644 --- a/lib/generated/l10n/l10n_ko.dart +++ b/lib/generated/l10n/l10n_ko.dart @@ -11,6 +11,19 @@ class L10nKo extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_lt.dart b/lib/generated/l10n/l10n_lt.dart index 92a774c..592aae0 100644 --- a/lib/generated/l10n/l10n_lt.dart +++ b/lib/generated/l10n/l10n_lt.dart @@ -11,6 +11,19 @@ class L10nLt extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_lv.dart b/lib/generated/l10n/l10n_lv.dart index ba09a05..9401b1d 100644 --- a/lib/generated/l10n/l10n_lv.dart +++ b/lib/generated/l10n/l10n_lv.dart @@ -11,6 +11,19 @@ class L10nLv extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'nē'; diff --git a/lib/generated/l10n/l10n_nb.dart b/lib/generated/l10n/l10n_nb.dart index 9ec5fc8..4eccdf3 100644 --- a/lib/generated/l10n/l10n_nb.dart +++ b/lib/generated/l10n/l10n_nb.dart @@ -11,6 +11,19 @@ class L10nNb extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_nl.dart b/lib/generated/l10n/l10n_nl.dart index 0a5dd1e..d870b45 100644 --- a/lib/generated/l10n/l10n_nl.dart +++ b/lib/generated/l10n/l10n_nl.dart @@ -11,6 +11,19 @@ class L10nNl extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'true'; diff --git a/lib/generated/l10n/l10n_pl.dart b/lib/generated/l10n/l10n_pl.dart index 24fb716..9c5655e 100644 --- a/lib/generated/l10n/l10n_pl.dart +++ b/lib/generated/l10n/l10n_pl.dart @@ -11,6 +11,19 @@ class L10nPl extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_pt.dart b/lib/generated/l10n/l10n_pt.dart index 9b0eb9d..ee0a4ce 100644 --- a/lib/generated/l10n/l10n_pt.dart +++ b/lib/generated/l10n/l10n_pt.dart @@ -11,6 +11,19 @@ class L10nPt extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_ro.dart b/lib/generated/l10n/l10n_ro.dart index 5e0c83b..4868aae 100644 --- a/lib/generated/l10n/l10n_ro.dart +++ b/lib/generated/l10n/l10n_ro.dart @@ -11,6 +11,19 @@ class L10nRo extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_ru.dart b/lib/generated/l10n/l10n_ru.dart index 4828b09..ac3aeb2 100644 --- a/lib/generated/l10n/l10n_ru.dart +++ b/lib/generated/l10n/l10n_ru.dart @@ -11,6 +11,19 @@ class L10nRu extends L10n { @override String get noSendPermission => 'Вы не можете отправлять сообщения'; + @override + String get noMessagesYet => 'Нет сообщений'; + + @override + String get longPressToRecordVoiceMessage => + 'Зажмите, чтобы записать голосовое сообщение.'; + + @override + String get pause => 'Пауза'; + + @override + String get resume => 'Продолжить'; + @override String get alwaysUse24HourFormat => 'нет'; diff --git a/lib/generated/l10n/l10n_sk.dart b/lib/generated/l10n/l10n_sk.dart index 0143e57..66942f2 100644 --- a/lib/generated/l10n/l10n_sk.dart +++ b/lib/generated/l10n/l10n_sk.dart @@ -11,6 +11,19 @@ class L10nSk extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_sl.dart b/lib/generated/l10n/l10n_sl.dart index e6a92e4..2914d84 100644 --- a/lib/generated/l10n/l10n_sl.dart +++ b/lib/generated/l10n/l10n_sl.dart @@ -11,6 +11,19 @@ class L10nSl extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_sr.dart b/lib/generated/l10n/l10n_sr.dart index 89c7258..91c0835 100644 --- a/lib/generated/l10n/l10n_sr.dart +++ b/lib/generated/l10n/l10n_sr.dart @@ -11,6 +11,19 @@ class L10nSr extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_sv.dart b/lib/generated/l10n/l10n_sv.dart index 2b57a2c..531815c 100644 --- a/lib/generated/l10n/l10n_sv.dart +++ b/lib/generated/l10n/l10n_sv.dart @@ -11,6 +11,19 @@ class L10nSv extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_ta.dart b/lib/generated/l10n/l10n_ta.dart index 1ea0a40..28701fc 100644 --- a/lib/generated/l10n/l10n_ta.dart +++ b/lib/generated/l10n/l10n_ta.dart @@ -11,6 +11,19 @@ class L10nTa extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'தவறு'; diff --git a/lib/generated/l10n/l10n_te.dart b/lib/generated/l10n/l10n_te.dart index b43e78d..9264713 100644 --- a/lib/generated/l10n/l10n_te.dart +++ b/lib/generated/l10n/l10n_te.dart @@ -11,6 +11,19 @@ class L10nTe extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'తప్పుడు'; diff --git a/lib/generated/l10n/l10n_th.dart b/lib/generated/l10n/l10n_th.dart index f0b05d9..96a63ea 100644 --- a/lib/generated/l10n/l10n_th.dart +++ b/lib/generated/l10n/l10n_th.dart @@ -11,6 +11,19 @@ class L10nTh extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_tr.dart b/lib/generated/l10n/l10n_tr.dart index 00edb2b..5076833 100644 --- a/lib/generated/l10n/l10n_tr.dart +++ b/lib/generated/l10n/l10n_tr.dart @@ -11,6 +11,19 @@ class L10nTr extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/generated/l10n/l10n_uk.dart b/lib/generated/l10n/l10n_uk.dart index 121ba06..3aecbbc 100644 --- a/lib/generated/l10n/l10n_uk.dart +++ b/lib/generated/l10n/l10n_uk.dart @@ -11,6 +11,19 @@ class L10nUk extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'ні'; diff --git a/lib/generated/l10n/l10n_vi.dart b/lib/generated/l10n/l10n_vi.dart index c42c805..426f7cd 100644 --- a/lib/generated/l10n/l10n_vi.dart +++ b/lib/generated/l10n/l10n_vi.dart @@ -11,6 +11,19 @@ class L10nVi extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'Không'; diff --git a/lib/generated/l10n/l10n_zh.dart b/lib/generated/l10n/l10n_zh.dart index f7bf045..d9e20bf 100644 --- a/lib/generated/l10n/l10n_zh.dart +++ b/lib/generated/l10n/l10n_zh.dart @@ -11,6 +11,19 @@ class L10nZh extends L10n { @override String get noSendPermission => 'You can\'t send messages here'; + @override + String get noMessagesYet => 'No messages yet'; + + @override + String get longPressToRecordVoiceMessage => + 'Long press to record voice message.'; + + @override + String get pause => 'Pause'; + + @override + String get resume => 'Resume'; + @override String get alwaysUse24HourFormat => 'false'; diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 8e95006..3272989 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:extera_next/pages/chat/recovered_event_dialog.dart'; import 'package:extera_next/pages/chat/translated_event_dialog.dart'; -import 'package:extera_next/utils/file_description.dart'; import 'package:extera_next/utils/matrix_sdk_extensions/synapse_admin_extension.dart'; import 'package:extera_next/utils/translator.dart'; import 'package:flutter/foundation.dart'; @@ -18,7 +17,6 @@ import 'package:extera_next/generated/l10n/l10n.dart'; import 'package:go_router/go_router.dart'; import 'package:image_picker/image_picker.dart'; import 'package:matrix/matrix.dart'; -import 'package:record/record.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:universal_html/html.dart' as html; @@ -28,7 +26,6 @@ import 'package:extera_next/config/setting_keys.dart'; import 'package:extera_next/config/themes.dart'; import 'package:extera_next/pages/chat/chat_view.dart'; import 'package:extera_next/pages/chat/event_info_dialog.dart'; -import 'package:extera_next/pages/chat/recording_dialog.dart'; import 'package:extera_next/pages/chat_details/chat_details.dart'; import 'package:extera_next/utils/error_reporter.dart'; import 'package:extera_next/utils/file_selector.dart'; @@ -619,45 +616,39 @@ class ChatController extends State ); } - void voiceMessageAction() async { + Future onVoiceMessageSend( + String path, + int duration, + List waveform, + String? fileName, + ) async { final scaffoldMessenger = ScaffoldMessenger.of(context); - if (PlatformInfos.isAndroid) { - final info = await DeviceInfoPlugin().androidInfo; - if (info.version.sdkInt < 19) { - showOkAlertDialog( - context: context, - title: L10n.of(context).unsupportedAndroidVersion, - message: L10n.of(context).unsupportedAndroidVersionLong, - okLabel: L10n.of(context).close, - ); - return; - } - } + final audioFile = XFile(path); - if (await AudioRecorder().hasPermission() == false) return; - final result = await showDialog( + final bytesResult = await showFutureLoadingDialog( context: context, - barrierDismissible: false, - builder: (c) => const RecordingDialog(), + future: audioFile.readAsBytes, ); - if (result == null) return; - final audioFile = XFile(result.path); + final bytes = bytesResult.result; + if (bytes == null) return; + final file = MatrixAudioFile( - bytes: await audioFile.readAsBytes(), - name: result.fileName ?? audioFile.path, + bytes: bytes, + name: fileName ?? audioFile.path, ); + await room.sendFileEvent( file, inReplyTo: replyEvent, extraContent: { 'info': { ...file.info, - 'duration': result.duration, + 'duration': duration, }, 'org.matrix.msc3245.voice': {}, 'org.matrix.msc1767.audio': { - 'duration': result.duration, - 'waveform': result.waveform, + 'duration': duration, + 'waveform': waveform, }, }, ).catchError((e) { @@ -737,8 +728,11 @@ class ChatController extends State return; } final event = selectedEvents.single; - await mx.client.reportEvent(roomId, event.eventId, - reason: "Extera (Next) Redacted Event Recover"); + await mx.client.reportEvent( + roomId, + event.eventId, + reason: "Extera (Next) Redacted Event Recover", + ); final reports = await mx.client.getEventReports(); final report = reports.firstWhere( @@ -753,11 +747,14 @@ class ChatController extends State } Navigator.of(context).push(new MaterialPageRoute( - builder: (BuildContext ctx) { - return RecoveredEventDialog( - event: recoveredEvent!, timeline: timeline!); - }, - fullscreenDialog: true)); + builder: (BuildContext ctx) { + return RecoveredEventDialog( + event: recoveredEvent, + timeline: timeline!, + ); + }, + fullscreenDialog: true, + )); } void translateEventAction() async { @@ -769,12 +766,6 @@ class ChatController extends State } final event = selectedEvents.single; var text = event.isRichMessage ? event.formattedText : event.text; - if (text == null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context).errorTranslatingMessage)), - ); - return; - } var content = {...event.content}; try { text = await Translator.translate( diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index 0786be2..fbd4fa9 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; -import 'package:extera_next/generated/l10n/l10n.dart'; import 'package:matrix/matrix.dart'; import 'package:extera_next/config/app_config.dart'; -import 'package:extera_next/utils/other_party_can_receive.dart'; +import 'package:extera_next/generated/l10n/l10n.dart'; +import 'package:extera_next/pages/chat/recording_input_row.dart'; +import 'package:extera_next/pages/chat/recording_view_model.dart'; import 'package:extera_next/utils/platform_infos.dart'; import 'package:extera_next/widgets/avatar.dart'; import 'package:extera_next/widgets/matrix.dart'; @@ -21,325 +22,331 @@ class ChatInputRow extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); - if (controller.showEmojiPicker && - controller.emojiPickerType == EmojiPickerType.reaction) { - return const SizedBox.shrink(); - } + const height = 48.0; - if (!controller.room.canSendDefaultMessages) { - return Center( - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Text( - L10n.of(context).noSendPermission, - style: theme.textTheme.bodySmall, - textAlign: TextAlign.center, - ), - ), - ); - } + final selectedTextButtonStyle = TextButton.styleFrom( + foregroundColor: theme.colorScheme.onTertiaryContainer, + ); - // if (!controller.room.otherPartyCanReceiveMessages) { - // return Center( - // child: Padding( - // padding: const EdgeInsets.all(12.0), - // child: Text( - // L10n.of(context).otherPartyNotLoggedIn, - // style: theme.textTheme.bodySmall, - // textAlign: TextAlign.center, - // ), - // ), - // ); - // } - - - - return Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: controller.selectMode - ? [ - if (controller.selectedEvents - .every((event) => event.status == EventStatus.error)) - SizedBox( - height: height, - child: TextButton( - style: TextButton.styleFrom( - foregroundColor: theme.colorScheme.error, + return RecordingViewModel( + builder: (context, recordingViewModel) { + if (recordingViewModel.isRecording) { + return RecordingInputRow( + state: recordingViewModel, + onSend: controller.onVoiceMessageSend, + ); + } + return Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: controller.selectMode + ? [ + if (controller.selectedEvents + .every((event) => event.status == EventStatus.error)) + SizedBox( + height: height, + child: TextButton( + style: TextButton.styleFrom( + foregroundColor: theme.colorScheme.error, + ), + onPressed: controller.deleteErrorEventsAction, + child: Row( + children: [ + const Icon(Icons.delete_forever_outlined), + Text(L10n.of(context).delete), + ], + ), + ), + ) + else + SizedBox( + height: height, + child: TextButton( + style: selectedTextButtonStyle, + onPressed: controller.forwardEventsAction, + child: Row( + children: [ + const Icon(Icons.keyboard_arrow_left_outlined), + Text(L10n.of(context).forward), + ], + ), + ), ), - onPressed: controller.deleteErrorEventsAction, - child: Row( - children: [ - const Icon(Icons.delete), - Text(L10n.of(context).delete), + controller.selectedEvents.length == 1 + ? controller.selectedEvents.first + .getDisplayEvent(controller.timeline!) + .status + .isSent + ? SizedBox( + height: height, + child: TextButton( + style: selectedTextButtonStyle, + onPressed: controller.replyAction, + child: Row( + children: [ + Text(L10n.of(context).reply), + const Icon(Icons.keyboard_arrow_right), + ], + ), + ), + ) + : SizedBox( + height: height, + child: TextButton( + style: selectedTextButtonStyle, + onPressed: controller.sendAgainAction, + child: Row( + children: [ + Text(L10n.of(context).tryToSendAgain), + const SizedBox(width: 4), + const Icon(Icons.send_outlined, size: 16), + ], + ), + ), + ) + : const SizedBox.shrink(), + ] + : [ + const SizedBox(width: 4), + AnimatedContainer( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + width: + controller.sendController.text.isNotEmpty ? 0 : height, + height: height, + alignment: Alignment.center, + decoration: const BoxDecoration(), + clipBehavior: Clip.hardEdge, + child: PopupMenuButton( + useRootNavigator: true, + icon: const Icon(Icons.add_circle_outline), + iconColor: theme.colorScheme.onPrimaryContainer, + onSelected: controller.onAddPopupMenuButtonSelected, + itemBuilder: (BuildContext context) => + >[ + if (PlatformInfos.isMobile) + PopupMenuItem( + value: 'location', + child: ListTile( + leading: CircleAvatar( + backgroundColor: + theme.colorScheme.onPrimaryContainer, + foregroundColor: + theme.colorScheme.primaryContainer, + child: const Icon(Icons.gps_fixed_outlined), + ), + title: Text(L10n.of(context).shareLocation), + contentPadding: const EdgeInsets.all(0), + ), + ), + // PopupMenuItem( + // value: 'image', + // child: ListTile( + // leading: CircleAvatar( + // backgroundColor: + // theme.colorScheme.onPrimaryContainer, + // foregroundColor: + // theme.colorScheme.primaryContainer, + // child: const Icon(Icons.photo_outlined), + // ), + // title: Text(L10n.of(context).sendImage), + // contentPadding: const EdgeInsets.all(0), + // ), + // ), + // PopupMenuItem( + // value: 'video', + // child: ListTile( + // leading: CircleAvatar( + // backgroundColor: + // theme.colorScheme.onPrimaryContainer, + // foregroundColor: + // theme.colorScheme.primaryContainer, + // child: + // const Icon(Icons.video_camera_back_outlined), + // ), + // title: Text(L10n.of(context).sendVideo), + // contentPadding: const EdgeInsets.all(0), + // ), + // ), + PopupMenuItem( + value: 'file', + child: ListTile( + leading: CircleAvatar( + backgroundColor: + theme.colorScheme.onPrimaryContainer, + foregroundColor: + theme.colorScheme.primaryContainer, + child: const Icon(Icons.attachment_outlined), + ), + title: Text(L10n.of(context).sendFile), + contentPadding: const EdgeInsets.all(0), + ), + ), ], ), ), - ) - else - SizedBox( - height: height, - child: TextButton( - onPressed: controller.forwardEventsAction, - child: Row( - children: [ - const Icon(Icons.keyboard_arrow_left_outlined), - Text(L10n.of(context).forward), - ], - ), - ), - ), - controller.selectedEvents.length == 1 - ? controller.selectedEvents.first - .getDisplayEvent(controller.timeline!) - .status - .isSent - ? SizedBox( - height: height, - child: TextButton( - onPressed: controller.replyAction, - child: Row( - children: [ - Text(L10n.of(context).reply), - const Icon(Icons.keyboard_arrow_right), - ], + if (PlatformInfos.isMobile) + AnimatedContainer( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + width: controller.sendController.text.isNotEmpty + ? 0 + : height, + height: height, + alignment: Alignment.center, + decoration: const BoxDecoration(), + clipBehavior: Clip.hardEdge, + child: PopupMenuButton( + useRootNavigator: true, + icon: const Icon(Icons.camera_alt_outlined), + onSelected: controller.onAddPopupMenuButtonSelected, + iconColor: theme.colorScheme.onPrimaryContainer, + itemBuilder: (context) => [ + PopupMenuItem( + value: 'camera-video', + child: ListTile( + leading: CircleAvatar( + backgroundColor: + theme.colorScheme.onPrimaryContainer, + foregroundColor: + theme.colorScheme.primaryContainer, + child: const Icon(Icons.videocam_outlined), + ), + title: Text(L10n.of(context).recordAVideo), + contentPadding: const EdgeInsets.all(0), ), ), - ) - : SizedBox( - height: height, - child: TextButton( - onPressed: controller.sendAgainAction, - child: Row( - children: [ - Text(L10n.of(context).tryToSendAgain), - const SizedBox(width: 4), - const Icon(Icons.send_outlined, size: 16), - ], + PopupMenuItem( + value: 'camera', + child: ListTile( + leading: CircleAvatar( + backgroundColor: + theme.colorScheme.onPrimaryContainer, + foregroundColor: + theme.colorScheme.primaryContainer, + child: const Icon(Icons.camera_alt_outlined), + ), + title: Text(L10n.of(context).takeAPhoto), + contentPadding: const EdgeInsets.all(0), ), ), - ) - : const SizedBox.shrink(), - ] - : [ - const SizedBox(width: 4), - AnimatedContainer( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - width: controller.sendController.text.isNotEmpty ? 0 : height, - height: height, - alignment: Alignment.center, - decoration: const BoxDecoration(), - clipBehavior: Clip.hardEdge, - child: PopupMenuButton( - icon: const Icon(Icons.add_circle_outline), - iconColor: theme.colorScheme.onPrimaryContainer, - onSelected: controller.onAddPopupMenuButtonSelected, - itemBuilder: (BuildContext context) => - >[ - if (PlatformInfos.isMobile) - PopupMenuItem( - value: 'location', - child: ListTile( - leading: CircleAvatar( - backgroundColor: - theme.colorScheme.onPrimaryContainer, - foregroundColor: theme.colorScheme.primaryContainer, - child: const Icon(Icons.gps_fixed_outlined), - ), - title: Text(L10n.of(context).shareLocation), - contentPadding: const EdgeInsets.all(0), - ), - ), - // PopupMenuItem( - // value: 'image', - // child: ListTile( - // leading: CircleAvatar( - // backgroundColor: theme.colorScheme.onPrimaryContainer, - // foregroundColor: theme.colorScheme.primaryContainer, - // child: const Icon(Icons.photo_outlined), - // ), - // title: Text(L10n.of(context).sendImage), - // contentPadding: const EdgeInsets.all(0), - // ), - // ), - // PopupMenuItem( - // value: 'video', - // child: ListTile( - // leading: CircleAvatar( - // backgroundColor: theme.colorScheme.onPrimaryContainer, - // foregroundColor: theme.colorScheme.primaryContainer, - // child: const Icon(Icons.video_camera_back_outlined), - // ), - // title: Text(L10n.of(context).sendVideo), - // contentPadding: const EdgeInsets.all(0), - // ), - // ), - PopupMenuItem( - value: 'file', - child: ListTile( - leading: CircleAvatar( - backgroundColor: theme.colorScheme.onPrimaryContainer, - foregroundColor: theme.colorScheme.primaryContainer, - child: const Icon(Icons.attachment_outlined), - ), - title: Text(L10n.of(context).sendFile), - contentPadding: const EdgeInsets.all(0), + ], ), ), - ], - ), - ), - if (PlatformInfos.isMobile) - AnimatedContainer( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - width: controller.sendController.text.isNotEmpty ? 0 : height, - height: height, - alignment: Alignment.center, - decoration: const BoxDecoration(), - clipBehavior: Clip.hardEdge, - child: PopupMenuButton( - icon: const Icon(Icons.camera_alt_outlined), - onSelected: controller.onAddPopupMenuButtonSelected, - iconColor: theme.colorScheme.onPrimaryContainer, - itemBuilder: (context) => [ - PopupMenuItem( - value: 'camera-video', - child: ListTile( - leading: CircleAvatar( - backgroundColor: - theme.colorScheme.onPrimaryContainer, - foregroundColor: theme.colorScheme.primaryContainer, - child: const Icon(Icons.videocam_outlined), - ), - title: Text(L10n.of(context).recordAVideo), - contentPadding: const EdgeInsets.all(0), + Container( + height: height, + width: height, + alignment: Alignment.center, + child: IconButton( + tooltip: L10n.of(context).emojis, + color: theme.colorScheme.onPrimaryContainer, + icon: PageTransitionSwitcher( + transitionBuilder: ( + Widget child, + Animation primaryAnimation, + Animation secondaryAnimation, + ) { + return SharedAxisTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + transitionType: SharedAxisTransitionType.scaled, + fillColor: Colors.transparent, + child: child, + ); + }, + child: Icon( + controller.showEmojiPicker + ? Icons.keyboard + : Icons.add_reaction_outlined, + key: ValueKey(controller.showEmojiPicker), ), ), - PopupMenuItem( - value: 'camera', - child: ListTile( - leading: CircleAvatar( - backgroundColor: - theme.colorScheme.onPrimaryContainer, - foregroundColor: theme.colorScheme.primaryContainer, - child: const Icon(Icons.camera_alt_outlined), - ), - title: Text(L10n.of(context).takeAPhoto), - contentPadding: const EdgeInsets.all(0), - ), - ), - ], - ), - ), - Container( - height: height, - width: height, - alignment: Alignment.center, - child: IconButton( - tooltip: L10n.of(context).emojis, - color: theme.colorScheme.onPrimaryContainer, - icon: PageTransitionSwitcher( - transitionBuilder: ( - Widget child, - Animation primaryAnimation, - Animation secondaryAnimation, - ) { - return SharedAxisTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - transitionType: SharedAxisTransitionType.scaled, - fillColor: Colors.transparent, - child: child, - ); - }, - child: Icon( - controller.showEmojiPicker - ? Icons.keyboard - : Icons.add_reaction_outlined, - key: ValueKey(controller.showEmojiPicker), + onPressed: controller.emojiPickerAction, ), ), - onPressed: controller.emojiPickerAction, - ), - ), - if (Matrix.of(context).isMultiAccount && - Matrix.of(context).hasComplexBundles && - Matrix.of(context).currentBundle!.length > 1) - Container( - width: height, - height: height, - alignment: Alignment.center, - child: _ChatAccountPicker(controller), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 0.0), - child: InputBar( - room: controller.room, - minLines: 1, - maxLines: 8, - autofocus: !PlatformInfos.isMobile, - keyboardType: TextInputType.multiline, - textInputAction: - AppConfig.sendOnEnter == true && PlatformInfos.isMobile + if (Matrix.of(context).isMultiAccount && + Matrix.of(context).hasComplexBundles && + Matrix.of(context).currentBundle!.length > 1) + Container( + height: height, + width: height, + alignment: Alignment.center, + child: _ChatAccountPicker(controller), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 0.0), + child: InputBar( + room: controller.room, + minLines: 1, + maxLines: 8, + autofocus: !PlatformInfos.isMobile, + keyboardType: TextInputType.multiline, + textInputAction: AppConfig.sendOnEnter == true && + PlatformInfos.isMobile ? TextInputAction.send : null, - onSubmitted: controller.onInputBarSubmitted, - onSubmitImage: controller.sendImageFromClipBoard, - focusNode: controller.inputFocus, - controller: controller.sendController, - decoration: InputDecoration( - contentPadding: const EdgeInsets.only( - left: 6.0, - right: 6.0, - bottom: 6.0, - top: 3.0, + onSubmitted: controller.onInputBarSubmitted, + onSubmitImage: controller.sendImageFromClipBoard, + focusNode: controller.inputFocus, + controller: controller.sendController, + decoration: InputDecoration( + contentPadding: const EdgeInsets.only( + left: 6.0, + right: 6.0, + bottom: 6.0, + top: 3.0, + ), + counter: const SizedBox.shrink(), + hintText: L10n.of(context).writeAMessage, + hintMaxLines: 1, + border: InputBorder.none, + enabledBorder: InputBorder.none, + filled: false, + ), + onChanged: controller.onInputBarChanged, ), - hintText: L10n.of(context).writeAMessage, - hintMaxLines: 1, - border: InputBorder.none, - enabledBorder: InputBorder.none, - filled: false, ), - onChanged: controller.onInputBarChanged, ), - ), - ), - Container( - height: height, - width: height, - alignment: Alignment.center, - child: PlatformInfos.platformCanRecord && - controller.sendController.text.isEmpty - ? FloatingActionButton.small( - tooltip: L10n.of(context).voiceMessage, - onPressed: controller.voiceMessageAction, - elevation: 0, - heroTag: null, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(height), - ), - backgroundColor: theme.bubbleColor, - foregroundColor: theme.onBubbleColor, - child: const Icon(Icons.mic_none_outlined), - ) - : FloatingActionButton.small( - tooltip: L10n.of(context).send, - onPressed: controller.send, - elevation: 0, - heroTag: null, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(height), - ), - backgroundColor: theme.bubbleColor, - foregroundColor: theme.onBubbleColor, - child: const Icon(Icons.send_outlined), - ), - ), - ], + Container( + height: height, + width: height, + alignment: Alignment.center, + child: PlatformInfos.platformCanRecord && + controller.sendController.text.isEmpty + ? IconButton( + tooltip: L10n.of(context).voiceMessage, + onPressed: () => + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + L10n.of(context) + .longPressToRecordVoiceMessage, + ), + ), + ), + onLongPress: () => recordingViewModel + .startRecording(controller.room), + style: IconButton.styleFrom( + backgroundColor: theme.bubbleColor, + foregroundColor: theme.onBubbleColor, + ), + icon: const Icon(Icons.mic_none_outlined), + ) + : IconButton( + tooltip: L10n.of(context).send, + onPressed: controller.send, + style: IconButton.styleFrom( + backgroundColor: theme.bubbleColor, + foregroundColor: theme.onBubbleColor, + ), + icon: const Icon(Icons.send_outlined), + ), + ), + ], + ); + }, ); } } @@ -368,6 +375,7 @@ class _ChatAccountPicker extends StatelessWidget { child: FutureBuilder( future: controller.sendingClient.fetchOwnProfile(), builder: (context, snapshot) => PopupMenuButton( + useRootNavigator: true, onSelected: (mxid) => _popupMenuButtonSelected(mxid, context), itemBuilder: (BuildContext context) => clients .map( @@ -399,4 +407,4 @@ class _ChatAccountPicker extends StatelessWidget { ), ); } -} +} \ No newline at end of file diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 696c4e6..4567fc4 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -15,7 +15,6 @@ import 'package:extera_next/pages/chat/chat_app_bar_title.dart'; import 'package:extera_next/pages/chat/chat_event_list.dart'; import 'package:extera_next/pages/chat/encryption_button.dart'; import 'package:extera_next/pages/chat/pinned_events.dart'; -import 'package:extera_next/pages/chat/reactions_picker.dart'; import 'package:extera_next/pages/chat/reply_display.dart'; import 'package:extera_next/utils/account_config.dart'; import 'package:extera_next/utils/localized_exception_extension.dart'; diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index aab1457..accdd8e 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -372,14 +372,14 @@ class InputBar extends StatelessWidget { if (suggestion['type'] == 'user') { insertText = '${suggestion['mention']!} '; startText = replaceText.replaceAllMapped( - RegExp(r'(\s|^)(@[-\w]+)$'), - (Match m) => '${m[1]}$insertText', + RegExp(r'(?:\s|^)@([^ \[\]]+)$', unicode: true), + (Match m) => '$insertText', ); } if (suggestion['type'] == 'room') { insertText = '${suggestion['mxid']!} '; startText = replaceText.replaceAllMapped( - RegExp(r'(\s|^)(#[-\w]+)$'), + RegExp(r'(\s|^)(#[-\w]+)$', unicode: true), (Match m) => '${m[1]}$insertText', ); } diff --git a/lib/pages/chat/recording_dialog.dart b/lib/pages/chat/recording_dialog.dart deleted file mode 100644 index 03ba75c..0000000 --- a/lib/pages/chat/recording_dialog.dart +++ /dev/null @@ -1,256 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -import 'package:extera_next/generated/l10n/l10n.dart'; -import 'package:path/path.dart' as path_lib; -import 'package:path_provider/path_provider.dart'; -import 'package:record/record.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; - -import 'package:extera_next/config/app_config.dart'; -import 'package:extera_next/config/setting_keys.dart'; -import 'package:extera_next/utils/platform_infos.dart'; -import 'package:extera_next/widgets/matrix.dart'; -import 'events/audio_player.dart'; - -class RecordingDialog extends StatefulWidget { - const RecordingDialog({ - super.key, - }); - - @override - RecordingDialogState createState() => RecordingDialogState(); -} - -class RecordingDialogState extends State { - Timer? _recorderSubscription; - Duration _duration = Duration.zero; - - bool error = false; - - final _audioRecorder = AudioRecorder(); - final List amplitudeTimeline = []; - - String? fileName; - - Future startRecording() async { - final store = Matrix.of(context).store; - try { - final codec = kIsWeb - // Web seems to create webm instead of ogg when using opus encoder - // which does not play on iOS right now. So we use wav for now: - ? AudioEncoder.wav - // Everywhere else we use opus if supported by the platform: - : await _audioRecorder.isEncoderSupported(AudioEncoder.opus) - ? AudioEncoder.opus - : AudioEncoder.aacLc; - fileName = - 'recording${DateTime.now().microsecondsSinceEpoch}.${codec.fileExtension}'; - String? path; - if (!kIsWeb) { - final tempDir = await getTemporaryDirectory(); - path = path_lib.join(tempDir.path, fileName); - } - - final result = await _audioRecorder.hasPermission(); - if (result != true) { - setState(() => error = true); - return; - } - await WakelockPlus.enable(); - - await _audioRecorder.start( - RecordConfig( - bitRate: AppSettings.audioRecordingBitRate.getItem(store), - sampleRate: AppSettings.audioRecordingSamplingRate.getItem(store), - numChannels: AppSettings.audioRecordingNumChannels.getItem(store), - autoGain: AppSettings.audioRecordingAutoGain.getItem(store), - echoCancel: AppSettings.audioRecordingEchoCancel.getItem(store), - noiseSuppress: AppSettings.audioRecordingNoiseSuppress.getItem(store), - encoder: codec, - ), - path: path ?? '', - ); - setState(() => _duration = Duration.zero); - _recorderSubscription?.cancel(); - _recorderSubscription = - Timer.periodic(const Duration(milliseconds: 100), (_) async { - final amplitude = await _audioRecorder.getAmplitude(); - var value = 100 + amplitude.current * 2; - value = value < 1 ? 1 : value; - amplitudeTimeline.add(value); - setState(() { - _duration += const Duration(milliseconds: 100); - }); - }); - } catch (_) { - setState(() => error = true); - rethrow; - } - } - - @override - void initState() { - super.initState(); - startRecording(); - } - - @override - void dispose() { - WakelockPlus.disable(); - _recorderSubscription?.cancel(); - _audioRecorder.stop(); - super.dispose(); - } - - void _stopAndSend() async { - _recorderSubscription?.cancel(); - final path = await _audioRecorder.stop(); - - if (path == null) throw ('Recording failed!'); - const waveCount = AudioPlayerWidget.wavesCount; - final step = amplitudeTimeline.length < waveCount - ? 1 - : (amplitudeTimeline.length / waveCount).round(); - final waveform = []; - for (var i = 0; i < amplitudeTimeline.length; i += step) { - waveform.add((amplitudeTimeline[i] / 100 * 1024).round()); - } - Navigator.of(context, rootNavigator: false).pop( - RecordingResult( - path: path, - duration: _duration.inMilliseconds, - waveform: waveform, - fileName: fileName, - ), - ); - } - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - const maxDecibalWidth = 64.0; - final time = - '${_duration.inMinutes.toString().padLeft(2, '0')}:${(_duration.inSeconds % 60).toString().padLeft(2, '0')}'; - final content = error - ? Text(L10n.of(context).oopsSomethingWentWrong) - : Row( - children: [ - Container( - width: 16, - height: 16, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(32), - color: Colors.red, - ), - ), - Expanded( - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, - children: amplitudeTimeline.reversed - .take(26) - .toList() - .reversed - .map( - (amplitude) => Container( - margin: const EdgeInsets.only(left: 2), - width: 4, - decoration: BoxDecoration( - color: theme.colorScheme.primary, - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), - ), - height: maxDecibalWidth * (amplitude / 100), - ), - ) - .toList(), - ), - ), - const SizedBox(width: 8), - SizedBox( - width: 48, - child: Text(time), - ), - ], - ); - if (PlatformInfos.isCupertinoStyle) { - return CupertinoAlertDialog( - content: content, - actions: [ - CupertinoDialogAction( - onPressed: () => Navigator.of(context, rootNavigator: false).pop(), - child: Text( - L10n.of(context).cancel, - style: TextStyle( - color: theme.textTheme.bodyMedium?.color?.withAlpha(150), - ), - ), - ), - if (error != true) - CupertinoDialogAction( - onPressed: _stopAndSend, - child: Text(L10n.of(context).send), - ), - ], - ); - } - return AlertDialog( - content: content, - actions: [ - TextButton( - onPressed: () => Navigator.of(context, rootNavigator: false).pop(), - child: Text( - L10n.of(context).cancel, - style: TextStyle( - color: theme.colorScheme.error, - ), - ), - ), - if (error != true) - TextButton( - onPressed: _stopAndSend, - child: Text(L10n.of(context).send), - ), - ], - ); - } -} - -class RecordingResult { - final String path; - final int duration; - final List waveform; - final String? fileName; - - const RecordingResult({ - required this.path, - required this.duration, - required this.waveform, - required this.fileName, - }); -} - -extension on AudioEncoder { - String get fileExtension { - switch (this) { - case AudioEncoder.aacLc: - case AudioEncoder.aacEld: - case AudioEncoder.aacHe: - return 'm4a'; - case AudioEncoder.opus: - return 'ogg'; - case AudioEncoder.wav: - return 'wav'; - case AudioEncoder.amrNb: - case AudioEncoder.amrWb: - case AudioEncoder.flac: - case AudioEncoder.pcm16bits: - throw UnsupportedError('Not yet used'); - } - } -} diff --git a/lib/pages/chat/recording_input_row.dart b/lib/pages/chat/recording_input_row.dart new file mode 100644 index 0000000..b90fb0b --- /dev/null +++ b/lib/pages/chat/recording_input_row.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +import 'package:extera_next/config/themes.dart'; + +import 'package:extera_next/generated/l10n/l10n.dart'; + +import 'package:extera_next/pages/chat/recording_view_model.dart'; + +class RecordingInputRow extends StatelessWidget { + final RecordingViewModelState state; + + final Future Function(String, int, List, String?) onSend; + + const RecordingInputRow({ + required this.state, + required this.onSend, + super.key, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + const maxDecibalWidth = 36.0; + + final time = + '${state.duration.inMinutes.toString().padLeft(2, '0')}:${(state.duration.inSeconds % 60).toString().padLeft(2, '0')}'; + + return Row( + children: [ + IconButton( + tooltip: L10n.of(context).cancel, + icon: const Icon(Icons.delete_outlined), + color: theme.colorScheme.error, + onPressed: state.cancel, + ), + if (state.isPaused) + IconButton( + tooltip: L10n.of(context).resume, + icon: const Icon(Icons.play_circle_outline_outlined), + onPressed: state.resume, + ) + else + IconButton( + tooltip: L10n.of(context).pause, + icon: const Icon(Icons.pause_circle_outline_outlined), + onPressed: state.pause, + ), + Text(time), + const SizedBox(width: 8), + Expanded( + child: LayoutBuilder( + builder: (context, constraints) { + const width = 4; + + return Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: state.amplitudeTimeline.reversed + .take((constraints.maxWidth / (width + 2)).floor()) + .toList() + .reversed + .map( + (amplitude) => Container( + margin: const EdgeInsets.only(left: 2), + width: width.toDouble(), + decoration: BoxDecoration( + color: theme.colorScheme.primary, + borderRadius: BorderRadius.circular(2), + ), + height: maxDecibalWidth * (amplitude / 100), + ), + ) + .toList(), + ); + }, + ), + ), + IconButton( + style: IconButton.styleFrom( + disabledBackgroundColor: theme.bubbleColor.withAlpha(128), + backgroundColor: theme.bubbleColor, + foregroundColor: theme.onBubbleColor, + ), + tooltip: L10n.of(context).sendAudio, + icon: state.isSending + ? const SizedBox.square( + dimension: 24, + child: CircularProgressIndicator.adaptive(), + ) + : const Icon(Icons.send_outlined), + onPressed: state.isSending ? null : () => state.stopAndSend(onSend), + ), + ], + ); + } +} diff --git a/lib/pages/chat/recording_view_model.dart b/lib/pages/chat/recording_view_model.dart new file mode 100644 index 0000000..0054385 --- /dev/null +++ b/lib/pages/chat/recording_view_model.dart @@ -0,0 +1,230 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:matrix/matrix.dart'; +import 'package:path/path.dart' as path_lib; +import 'package:path_provider/path_provider.dart'; +import 'package:record/record.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; + +import 'package:extera_next/config/setting_keys.dart'; +import 'package:extera_next/generated/l10n/l10n.dart'; +import 'package:extera_next/utils/platform_infos.dart'; +import 'package:extera_next/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; +import 'package:extera_next/widgets/matrix.dart'; +import 'events/audio_player.dart'; + +class RecordingViewModel extends StatefulWidget { + final Widget Function(BuildContext, RecordingViewModelState) builder; + + const RecordingViewModel({ + required this.builder, + super.key, + }); + + @override + RecordingViewModelState createState() => RecordingViewModelState(); +} + +class RecordingViewModelState extends State { + Timer? _recorderSubscription; + Duration duration = Duration.zero; + + bool error = false; + bool isSending = false; + + bool get isRecording => _audioRecorder != null; + + AudioRecorder? _audioRecorder; + final List amplitudeTimeline = []; + + String? fileName; + + bool isPaused = false; + + Future startRecording(Room room) async { + room.client.getConfig(); // Preload server file configuration. + if (PlatformInfos.isAndroid) { + final info = await DeviceInfoPlugin().androidInfo; + if (info.version.sdkInt < 19) { + showOkAlertDialog( + context: context, + title: L10n.of(context).unsupportedAndroidVersion, + message: L10n.of(context).unsupportedAndroidVersionLong, + okLabel: L10n.of(context).close, + ); + return; + } + } + + // TODO: add permission request + if (await AudioRecorder().hasPermission() == false) return; + + final store = Matrix.of(context).store; + + final audioRecorder = _audioRecorder ??= AudioRecorder(); + setState(() {}); + + try { + final codec = kIsWeb + // Web seems to create webm instead of ogg when using opus encoder + // which does not play on iOS right now. So we use wav for now: + ? AudioEncoder.wav + // Everywhere else we use opus if supported by the platform: + : await audioRecorder.isEncoderSupported(AudioEncoder.opus) + ? AudioEncoder.opus + : AudioEncoder.aacLc; + fileName = + 'recording${DateTime.now().microsecondsSinceEpoch}.${codec.fileExtension}'; + String? path; + if (!kIsWeb) { + final tempDir = await getTemporaryDirectory(); + path = path_lib.join(tempDir.path, fileName); + } + + final result = await audioRecorder.hasPermission(); + if (result != true) { + setState(() => error = true); + return; + } + await WakelockPlus.enable(); + + await audioRecorder.start( + RecordConfig( + bitRate: AppSettings.audioRecordingBitRate.getItem(store), + sampleRate: AppSettings.audioRecordingSamplingRate.getItem(store), + numChannels: AppSettings.audioRecordingNumChannels.getItem(store), + autoGain: AppSettings.audioRecordingAutoGain.getItem(store), + echoCancel: AppSettings.audioRecordingEchoCancel.getItem(store), + noiseSuppress: AppSettings.audioRecordingNoiseSuppress.getItem(store), + encoder: codec, + ), + path: path ?? '', + ); + setState(() => duration = Duration.zero); + _subscribe(); + } catch (_) { + setState(() => error = true); + rethrow; + } + } + + @override + void dispose() { + _reset(); + super.dispose(); + } + + void _subscribe() { + _recorderSubscription?.cancel(); + _recorderSubscription = + Timer.periodic(const Duration(milliseconds: 100), (_) async { + final amplitude = await _audioRecorder!.getAmplitude(); + var value = 100 + amplitude.current * 2; + value = value < 1 ? 1 : value; + amplitudeTimeline.add(value); + setState(() { + duration += const Duration(milliseconds: 100); + }); + }); + } + + void _reset() { + WakelockPlus.disable(); + _recorderSubscription?.cancel(); + _audioRecorder?.stop(); + _audioRecorder = null; + isSending = false; + error = false; + fileName = null; + duration = Duration.zero; + amplitudeTimeline.clear(); + isPaused = false; + } + + void cancel() { + setState(() { + _reset(); + }); + } + + void pause() { + _audioRecorder?.pause(); + _recorderSubscription?.cancel(); + setState(() { + isPaused = true; + }); + } + + void resume() { + _audioRecorder?.resume(); + _subscribe(); + setState(() { + isPaused = false; + }); + } + + void stopAndSend( + Future Function( + String path, + int duration, + List waveform, + String? fileName, + ) onSend, + ) async { + _recorderSubscription?.cancel(); + final path = await _audioRecorder?.stop(); + + if (path == null) throw ('Recording failed!'); + const waveCount = AudioPlayerWidget.wavesCount; + final step = amplitudeTimeline.length < waveCount + ? 1 + : (amplitudeTimeline.length / waveCount).round(); + final waveform = []; + for (var i = 0; i < amplitudeTimeline.length; i += step) { + waveform.add((amplitudeTimeline[i] / 100 * 1024).round()); + } + + setState(() { + isSending = true; + }); + try { + await onSend(path, duration.inMilliseconds, waveform, fileName); + } catch (e, s) { + Logs().e('Unable to send voice message', e, s); + setState(() { + isSending = false; + }); + return; + } + + cancel(); + } + + @override + Widget build(BuildContext context) => widget.builder(context, this); +} + +extension on AudioEncoder { + String get fileExtension { + switch (this) { + case AudioEncoder.aacLc: + case AudioEncoder.aacEld: + case AudioEncoder.aacHe: + return 'm4a'; + case AudioEncoder.opus: + return 'ogg'; + case AudioEncoder.wav: + return 'wav'; + case AudioEncoder.amrNb: + case AudioEncoder.amrWb: + case AudioEncoder.flac: + case AudioEncoder.pcm16bits: + throw UnsupportedError('Not yet used'); + } + } +} diff --git a/lib/pages/chat/recovered_event_dialog.dart b/lib/pages/chat/recovered_event_dialog.dart index abb52b9..9758ff6 100644 --- a/lib/pages/chat/recovered_event_dialog.dart +++ b/lib/pages/chat/recovered_event_dialog.dart @@ -1,6 +1,5 @@ import 'package:extera_next/config/themes.dart'; import 'package:extera_next/pages/chat/events/message.dart'; -import 'package:extera_next/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; diff --git a/lib/pages/chat/send_file_dialog.dart b/lib/pages/chat/send_file_dialog.dart index 193f3a1..d3a34ca 100644 --- a/lib/pages/chat/send_file_dialog.dart +++ b/lib/pages/chat/send_file_dialog.dart @@ -10,7 +10,6 @@ import 'package:extera_next/generated/l10n/l10n.dart'; import 'package:matrix/matrix.dart'; import 'package:mime/mime.dart'; -import 'package:extera_next/config/app_config.dart'; import 'package:extera_next/utils/localized_exception_extension.dart'; import 'package:extera_next/utils/matrix_sdk_extensions/matrix_file_extension.dart'; import 'package:extera_next/utils/other_party_can_receive.dart'; diff --git a/lib/pages/chat/translated_event_dialog.dart b/lib/pages/chat/translated_event_dialog.dart index c1e412c..337701f 100644 --- a/lib/pages/chat/translated_event_dialog.dart +++ b/lib/pages/chat/translated_event_dialog.dart @@ -1,6 +1,5 @@ import 'package:extera_next/config/themes.dart'; import 'package:extera_next/pages/chat/events/message.dart'; -import 'package:extera_next/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index f930ed9..f5f4ccc 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -207,8 +207,9 @@ class ChatDetailsView extends StatelessWidget { ), ], ), - Divider(color: theme.dividerColor), - if (!room.canChangeStateEvent(EventTypes.RoomTopic)) + if (room.canChangeStateEvent(EventTypes.RoomTopic) || + room.topic.isNotEmpty) ...[ + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context).chatDescription, @@ -217,53 +218,46 @@ class ChatDetailsView extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - ) - else + trailing: + room.canChangeStateEvent(EventTypes.RoomTopic) + ? IconButton( + onPressed: controller.setTopicAction, + tooltip: + L10n.of(context).setChatDescription, + icon: const Icon(Icons.edit_outlined), + ) + : null, + ), Padding( - padding: const EdgeInsets.all(16.0), - child: TextButton.icon( - onPressed: controller.setTopicAction, - label: Text(L10n.of(context).setChatDescription), - icon: const Icon(Icons.edit_outlined), - style: TextButton.styleFrom( - iconColor: - theme.colorScheme.onSecondaryContainer, - backgroundColor: - theme.colorScheme.secondaryContainer, - foregroundColor: - theme.colorScheme.onSecondaryContainer, + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + ), + child: SelectableLinkify( + text: room.topic.isEmpty + ? L10n.of(context).noChatDescriptionYet + : room.topic, + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), + options: const LinkifyOptions(humanize: false), + linkStyle: const TextStyle( + color: Colors.blueAccent, + decorationColor: Colors.blueAccent, ), + style: TextStyle( + fontSize: 14, + fontStyle: room.topic.isEmpty + ? FontStyle.italic + : FontStyle.normal, + color: theme.textTheme.bodyMedium!.color, + decorationColor: + theme.textTheme.bodyMedium!.color, + ), + onOpen: (url) => + UrlLauncher(context, url.url).launchUrl(), ), ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - ), - child: SelectableLinkify( - text: room.topic.isEmpty - ? L10n.of(context).noChatDescriptionYet - : room.topic, - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), - options: const LinkifyOptions(humanize: false), - linkStyle: const TextStyle( - color: Colors.blueAccent, - decorationColor: Colors.blueAccent, - ), - style: TextStyle( - fontSize: 14, - fontStyle: room.topic.isEmpty - ? FontStyle.italic - : FontStyle.normal, - color: theme.textTheme.bodyMedium!.color, - decorationColor: - theme.textTheme.bodyMedium!.color, - ), - onOpen: (url) => - UrlLauncher(context, url.url).launchUrl(), - ), - ), - const SizedBox(height: 16), + const SizedBox(height: 16), + ], Divider(color: theme.dividerColor), ListTile( leading: CircleAvatar( @@ -366,4 +360,4 @@ class ChatDetailsView extends StatelessWidget { }, ); } -} +} \ No newline at end of file diff --git a/lib/pages/download_manager/download_manager.dart b/lib/pages/download_manager/download_manager.dart index 1c48902..359b9f4 100644 --- a/lib/pages/download_manager/download_manager.dart +++ b/lib/pages/download_manager/download_manager.dart @@ -27,33 +27,33 @@ class Download { try { final mx = Matrix.of(context).client; // final directory = await getDownloadsDirectory(); - downloadPath = - "/sdcard/Download/Extera"; + downloadPath = "/sdcard/Download/Extera"; httpUrl = (await Uri.parse(url).getDownloadUri(mx)).toString(); if (downloadPath != null) { // Create Dio instance final dio = Dio(); - + ct = CancelToken(); // Download the file - response = dio.download( - httpUrl, - "$downloadPath/$name", - onReceiveProgress: (received, total) { - receivedBytes = received; - totalBytes = total; - progress = (receivedBytes / totalBytes) * 100; - print("Download progress: $progress%"); - }, - options: Options( - responseType: ResponseType.bytes, - headers: {'authorization': "Bearer ${mx.accessToken}"} - ), - cancelToken: ct - ); + response = dio.download(httpUrl, "$downloadPath/$name", + onReceiveProgress: (received, total) { + receivedBytes = received; + totalBytes = total; + progress = (receivedBytes / totalBytes) * 100; + if (progress == 100) { + Provider.of(context) + .downloads + .remove(this); + } + print("Download progress: $progress%"); + }, + options: Options( + responseType: ResponseType.bytes, + headers: {'authorization': "Bearer ${mx.accessToken}"}), + cancelToken: ct); print("Download completed and saved to $downloadPath/$name"); } } catch (e) { @@ -63,6 +63,7 @@ class Download { void cancel() async { ct.cancel(); + Provider.of(context).downloads.remove(this); } } diff --git a/lib/utils/file_selector.dart b/lib/utils/file_selector.dart index e6edfbc..49b95fd 100644 --- a/lib/utils/file_selector.dart +++ b/lib/utils/file_selector.dart @@ -13,37 +13,18 @@ Future> selectFiles( FileSelectorType type = FileSelectorType.any, bool allowMultiple = false, }) async { - if (!PlatformInfos.isLinux) { - final result = await AppLock.of(context).pauseWhile( - showFutureLoadingDialog( - context: context, - future: () => FilePicker.platform.pickFiles( - compressionQuality: 0, - allowMultiple: allowMultiple, - type: type.filePickerType, - allowedExtensions: type.extensions, - ), + final result = await AppLock.of(context).pauseWhile( + showFutureLoadingDialog( + context: context, + future: () => FilePicker.platform.pickFiles( + compressionQuality: 0, + allowMultiple: allowMultiple, + type: type.filePickerType, + allowedExtensions: type.extensions, ), - ); - return result.result?.xFiles ?? []; - } - - if (allowMultiple) { - return await AppLock.of(context).pauseWhile( - openFiles( - confirmButtonText: title, - acceptedTypeGroups: type.groups, - ), - ); - } - final file = await AppLock.of(context).pauseWhile( - openFile( - confirmButtonText: title, - acceptedTypeGroups: type.groups, ), ); - if (file == null) return []; - return [file]; + return result.result?.xFiles ?? []; } enum FileSelectorType { diff --git a/lib/widgets/avatar_page_header.dart b/lib/widgets/avatar_page_header.dart new file mode 100644 index 0000000..d62e541 --- /dev/null +++ b/lib/widgets/avatar_page_header.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; + +import 'package:extera_next/config/themes.dart'; + +class AvatarPageHeader extends StatelessWidget { + final Widget avatar; + + final void Function()? onAvatarEdit; + + final Widget? textButtonLeft, textButtonRight; + + final List iconButtons; + + const AvatarPageHeader({ + super.key, + required this.avatar, + this.onAvatarEdit, + this.iconButtons = const [], + this.textButtonLeft, + this.textButtonRight, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + final onAvatarEdit = this.onAvatarEdit; + + return Center( + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: FluffyThemes.columnWidth), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + spacing: 8.0, + children: [ + Stack( + children: [ + avatar, + if (onAvatarEdit != null) + Positioned( + bottom: 0, + right: 0, + child: FloatingActionButton.small( + elevation: 2, + onPressed: onAvatarEdit, + heroTag: null, + child: const Icon(Icons.camera_alt_outlined), + ), + ), + ], + ), + TextButtonTheme( + data: TextButtonThemeData( + style: TextButton.styleFrom( + disabledForegroundColor: theme.colorScheme.onSurface, + foregroundColor: theme.colorScheme.onSurface, + textStyle: const TextStyle(fontWeight: FontWeight.normal), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: LayoutBuilder( + builder: (context, constraints) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth / 2, + ), + child: textButtonLeft, + ), + ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth / 2, + ), + child: textButtonRight, + ), + ], + ); + }, + ), + ), + ), + IconButtonTheme( + data: IconButtonThemeData( + style: IconButton.styleFrom( + backgroundColor: theme.colorScheme.surfaceContainer, + iconSize: 24, + padding: const EdgeInsets.all(16), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: iconButtons, + ), + ), + const SizedBox(height: 0.0), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/chat_settings_popup_menu.dart b/lib/widgets/chat_settings_popup_menu.dart index a1b4569..05c5426 100644 --- a/lib/widgets/chat_settings_popup_menu.dart +++ b/lib/widgets/chat_settings_popup_menu.dart @@ -10,7 +10,7 @@ import 'package:extera_next/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog import 'package:extera_next/widgets/future_loading_dialog.dart'; import 'matrix.dart'; -enum ChatPopupMenuActions { details, mute, unmute, leave, search } +enum ChatPopupMenuActions { details, mute, unmute, emote, leave, search } class ChatSettingsPopupMenu extends StatefulWidget { final Room room; @@ -31,6 +31,17 @@ class ChatSettingsPopupMenuState extends State { super.dispose(); } + void goToEmoteSettings() async { + final room = widget.room; + if ((room.states['im.ponies.room_emotes'] ?? {}) + .keys + .any((String s) => s.isNotEmpty)) { + context.push('/rooms/${room.id}/details/multiple_emotes'); + } else { + context.push('/rooms/${room.id}/details/emotes'); + } + } + @override Widget build(BuildContext context) { notificationChangeSub ??= Matrix.of(context) @@ -73,6 +84,9 @@ class ChatSettingsPopupMenuState extends State { } } break; + case ChatPopupMenuActions.emote: + goToEmoteSettings(); + break; case ChatPopupMenuActions.mute: await showFutureLoadingDialog( context: context, diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index 873cac5..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,2377 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" - url: "https://pub.dev" - source: hosted - version: "67.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" - url: "https://pub.dev" - source: hosted - version: "6.4.1" - animations: - dependency: "direct main" - description: - name: animations - sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb - url: "https://pub.dev" - source: hosted - version: "2.0.11" - ansicolor: - dependency: transitive - description: - name: ansicolor - sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" - url: "https://pub.dev" - source: hosted - version: "2.0.3" - app_links: - dependency: "direct main" - description: - name: app_links - sha256: "5f88447519add627fe1cbcab4fd1da3d4fed15b9baf29f28b22535c95ecee3e8" - url: "https://pub.dev" - source: hosted - version: "6.4.1" - app_links_linux: - dependency: transitive - description: - name: app_links_linux - sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 - url: "https://pub.dev" - source: hosted - version: "1.0.3" - app_links_platform_interface: - dependency: transitive - description: - name: app_links_platform_interface - sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - app_links_web: - dependency: transitive - description: - name: app_links_web - sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 - url: "https://pub.dev" - source: hosted - version: "1.0.4" - archive: - dependency: "direct main" - description: - name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.dev" - source: hosted - version: "4.0.7" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: "direct main" - description: - name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.dev" - source: hosted - version: "2.13.0" - audio_session: - dependency: transitive - description: - name: audio_session - sha256: "2b7fff16a552486d078bfc09a8cde19f426dc6d6329262b684182597bec5b1ac" - url: "https://pub.dev" - source: hosted - version: "0.1.25" - badges: - dependency: "direct main" - description: - name: badges - sha256: a7b6bbd60dce418df0db3058b53f9d083c22cdb5132a052145dc267494df0b84 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - barbecue: - dependency: transitive - description: - name: barbecue - sha256: e3a0afaf9005e466887d6c87411a2ddd8d72fc46db3caabf278ee600f1e2f92c - url: "https://pub.dev" - source: hosted - version: "0.4.0" - base58check: - dependency: transitive - description: - name: base58check - sha256: "6c300dfc33e598d2fe26319e13f6243fea81eaf8204cb4c6b69ef20a625319a5" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - blurhash_dart: - dependency: "direct main" - description: - name: blurhash_dart - sha256: "43955b6c2e30a7d440028d1af0fa185852f3534b795cc6eb81fbf397b464409f" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - build_cli_annotations: - dependency: transitive - description: - name: build_cli_annotations - sha256: e563c2e01de8974566a1998410d3f6f03521788160a02503b0b1f1a46c7b3d95 - url: "https://pub.dev" - source: hosted - version: "2.1.1" - canonical_json: - dependency: transitive - description: - name: canonical_json - sha256: d6be1dd66b420c6ac9f42e3693e09edf4ff6edfee26cb4c28c1c019fdb8c0c15 - url: "https://pub.dev" - source: hosted - version: "1.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - charcode: - dependency: transitive - description: - name: charcode - sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a - url: "https://pub.dev" - source: hosted - version: "1.4.0" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.dev" - source: hosted - version: "2.0.4" - chewie: - dependency: "direct main" - description: - name: chewie - sha256: "44bcfc5f0dfd1de290c87c9d86a61308b3282a70b63435d5557cfd60f54a69ca" - url: "https://pub.dev" - source: hosted - version: "1.13.0" - cli_config: - dependency: transitive - description: - name: cli_config - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec - url: "https://pub.dev" - source: hosted - version: "0.2.0" - cli_util: - dependency: transitive - description: - name: cli_util - sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c - url: "https://pub.dev" - source: hosted - version: "0.4.2" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: "direct main" - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - colorize: - dependency: transitive - description: - name: colorize - sha256: "584746cd6ba1cba0633b6720f494fe6f9601c4170f0666c1579d2aa2a61071ba" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - console: - dependency: transitive - description: - name: console - sha256: e04e7824384c5b39389acdd6dc7d33f3efe6b232f6f16d7626f194f6a01ad69a - url: "https://pub.dev" - source: hosted - version: "4.1.0" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - coverage: - dependency: transitive - description: - name: coverage - sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" - url: "https://pub.dev" - source: hosted - version: "1.15.0" - cross_file: - dependency: "direct main" - description: - name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" - url: "https://pub.dev" - source: hosted - version: "0.3.4+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.dev" - source: hosted - version: "3.0.6" - csslib: - dependency: transitive - description: - name: csslib - sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" - url: "https://pub.dev" - source: hosted - version: "1.0.2" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - dart_webrtc: - dependency: transitive - description: - name: dart_webrtc - sha256: "51bcda4ba5d7dd9e65a309244ce3ac0b58025e6e1f6d7442cee4cd02134ef65f" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - dbus: - dependency: transitive - description: - name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.dev" - source: hosted - version: "0.7.11" - desktop_drop: - dependency: "direct main" - description: - name: desktop_drop - sha256: d55a010fe46c8e8fcff4ea4b451a9ff84a162217bdb3b2a0aa1479776205e15d - url: "https://pub.dev" - source: hosted - version: "0.4.4" - desktop_notifications: - dependency: "direct main" - description: - name: desktop_notifications - sha256: "6d92694ad6e9297a862c5ff7dd6b8ff64c819972557754769f819d2209612927" - url: "https://pub.dev" - source: hosted - version: "0.6.3" - device_info_plus: - dependency: "direct main" - description: - name: device_info_plus - sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 - url: "https://pub.dev" - source: hosted - version: "10.1.2" - device_info_plus_platform_interface: - dependency: transitive - description: - name: device_info_plus_platform_interface - sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f - url: "https://pub.dev" - source: hosted - version: "7.0.3" - dio: - dependency: "direct main" - description: - name: dio - sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9 - url: "https://pub.dev" - source: hosted - version: "5.9.0" - dio_web_adapter: - dependency: transitive - description: - name: dio_web_adapter - sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - dynamic_color: - dependency: "direct main" - description: - name: dynamic_color - sha256: "43a5a6679649a7731ab860334a5812f2067c2d9ce6452cf069c5e0c25336c17c" - url: "https://pub.dev" - source: hosted - version: "1.8.1" - emoji_picker_flutter: - dependency: "direct main" - description: - name: emoji_picker_flutter - sha256: "08567e6f914d36c32091a96cf2f51d2558c47aa2bd47a590dc4f50e42e0965f6" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - emojis: - dependency: "direct main" - description: - name: emojis - sha256: "2e4d847c3f1e2670f30dc355909ce6fa7808b4e626c34a4dd503a360995a38bf" - url: "https://pub.dev" - source: hosted - version: "0.9.9" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - file_picker: - dependency: "direct main" - description: - name: file_picker - sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f - url: "https://pub.dev" - source: hosted - version: "10.3.3" - file_selector: - dependency: "direct main" - description: - name: file_selector - sha256: "5f1d15a7f17115038f433d1b0ea57513cc9e29a9d5338d166cb0bef3fa90a7a0" - url: "https://pub.dev" - source: hosted - version: "1.0.4" - file_selector_android: - dependency: transitive - description: - name: file_selector_android - sha256: "1ce58b609289551f8ec07265476720e77d19764339cc1d8e4df3c4d34dac6499" - url: "https://pub.dev" - source: hosted - version: "0.5.1+17" - file_selector_ios: - dependency: transitive - description: - name: file_selector_ios - sha256: fe9f52123af16bba4ad65bd7e03defbbb4b172a38a8e6aaa2a869a0c56a5f5fb - url: "https://pub.dev" - source: hosted - version: "0.5.3+2" - file_selector_linux: - dependency: transitive - description: - name: file_selector_linux - sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" - url: "https://pub.dev" - source: hosted - version: "0.9.3+2" - file_selector_macos: - dependency: transitive - description: - name: file_selector_macos - sha256: "19124ff4a3d8864fdc62072b6a2ef6c222d55a3404fe14893a3c02744907b60c" - url: "https://pub.dev" - source: hosted - version: "0.9.4+4" - file_selector_platform_interface: - dependency: transitive - description: - name: file_selector_platform_interface - sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b - url: "https://pub.dev" - source: hosted - version: "2.6.2" - file_selector_web: - dependency: transitive - description: - name: file_selector_web - sha256: c4c0ea4224d97a60a7067eca0c8fd419e708ff830e0c83b11a48faf566cec3e7 - url: "https://pub.dev" - source: hosted - version: "0.9.4+2" - file_selector_windows: - dependency: transitive - description: - name: file_selector_windows - sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" - url: "https://pub.dev" - source: hosted - version: "0.9.3+4" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_cache_manager: - dependency: "direct main" - description: - name: flutter_cache_manager - sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" - url: "https://pub.dev" - source: hosted - version: "3.4.1" - flutter_driver: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_foreground_task: - dependency: "direct main" - description: - name: flutter_foreground_task - sha256: "6cf10a27f5e344cd2ecad0752d3a5f4ec32846d82fda8753b3fe2480ebb832a3" - url: "https://pub.dev" - source: hosted - version: "6.5.0" - flutter_highlighter: - dependency: "direct main" - description: - name: flutter_highlighter - sha256: "93173afd47a9ada53f3176371755e7ea4a1065362763976d06d6adfb4d946e10" - url: "https://pub.dev" - source: hosted - version: "0.1.1" - flutter_keyboard_visibility: - dependency: transitive - description: - name: flutter_keyboard_visibility - sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_keyboard_visibility_linux: - dependency: transitive - description: - name: flutter_keyboard_visibility_linux - sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - flutter_keyboard_visibility_macos: - dependency: transitive - description: - name: flutter_keyboard_visibility_macos - sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 - url: "https://pub.dev" - source: hosted - version: "1.0.0" - flutter_keyboard_visibility_platform_interface: - dependency: transitive - description: - name: flutter_keyboard_visibility_platform_interface - sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 - url: "https://pub.dev" - source: hosted - version: "2.0.0" - flutter_keyboard_visibility_web: - dependency: transitive - description: - name: flutter_keyboard_visibility_web - sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 - url: "https://pub.dev" - source: hosted - version: "2.0.0" - flutter_keyboard_visibility_windows: - dependency: transitive - description: - name: flutter_keyboard_visibility_windows - sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 - url: "https://pub.dev" - source: hosted - version: "1.0.0" - flutter_linkify: - dependency: "direct main" - description: - name: flutter_linkify - sha256: "74669e06a8f358fee4512b4320c0b80e51cffc496607931de68d28f099254073" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - flutter_local_notifications: - dependency: "direct main" - description: - name: flutter_local_notifications - sha256: "674173fd3c9eda9d4c8528da2ce0ea69f161577495a9cc835a2a4ecd7eadeb35" - url: "https://pub.dev" - source: hosted - version: "17.2.4" - flutter_local_notifications_linux: - dependency: transitive - description: - name: flutter_local_notifications_linux - sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af - url: "https://pub.dev" - source: hosted - version: "4.0.1" - flutter_local_notifications_platform_interface: - dependency: transitive - description: - name: flutter_local_notifications_platform_interface - sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66" - url: "https://pub.dev" - source: hosted - version: "7.2.0" - flutter_localizations: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_map: - dependency: "direct main" - description: - name: flutter_map - sha256: "87cc8349b8fa5dccda5af50018c7374b6645334a0d680931c1fe11bce88fa5bb" - url: "https://pub.dev" - source: hosted - version: "6.2.1" - flutter_native_splash: - dependency: "direct dev" - description: - name: flutter_native_splash - sha256: "8321a6d11a8d13977fa780c89de8d257cce3d841eecfb7a4cadffcc4f12d82dc" - url: "https://pub.dev" - source: hosted - version: "2.4.6" - flutter_new_badger: - dependency: "direct main" - description: - name: flutter_new_badger - sha256: d3742ace8009663db1ac6ba0377b092f479c35deb33e05514ba05cc0b0a5aaaa - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter_openssl_crypto: - dependency: "direct main" - description: - name: flutter_openssl_crypto - sha256: "293b4fcda13ab0710645a16e82f3d5b7de19bfc0ab2d06bcdb87637222eda5e1" - url: "https://pub.dev" - source: hosted - version: "0.5.0" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: b0694b7fb1689b0e6cc193b3f1fcac6423c4f93c74fb20b806c6b6f196db0c31 - url: "https://pub.dev" - source: hosted - version: "2.0.30" - flutter_rust_bridge: - dependency: "direct main" - description: - name: flutter_rust_bridge - sha256: "37ef40bc6f863652e865f0b2563ea07f0d3c58d8efad803cc01933a4b2ee067e" - url: "https://pub.dev" - source: hosted - version: "2.11.1" - flutter_secure_storage: - dependency: "direct main" - description: - name: flutter_secure_storage - sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" - url: "https://pub.dev" - source: hosted - version: "9.2.4" - flutter_secure_storage_linux: - dependency: transitive - description: - name: flutter_secure_storage_linux - sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 - url: "https://pub.dev" - source: hosted - version: "1.2.3" - flutter_secure_storage_macos: - dependency: transitive - description: - name: flutter_secure_storage_macos - sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" - url: "https://pub.dev" - source: hosted - version: "3.1.3" - flutter_secure_storage_platform_interface: - dependency: transitive - description: - name: flutter_secure_storage_platform_interface - sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_secure_storage_web: - dependency: transitive - description: - name: flutter_secure_storage_web - sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - flutter_secure_storage_windows: - dependency: transitive - description: - name: flutter_secure_storage_windows - sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - flutter_shortcuts_new: - dependency: "direct main" - description: - name: flutter_shortcuts_new - sha256: "16ee1c8a9bc9586b5117ebb774a8ff6b396f856743e97251eb483c4dc5769d7f" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_typeahead: - dependency: "direct main" - description: - path: "." - ref: main - resolved-ref: "3e209e67aa6e780cba61ced06cf49d2babbbcaa4" - url: "https://github.com/famedly/flutter_typeahead.git" - source: git - version: "5.2.0" - flutter_vodozemac: - dependency: "direct main" - description: - name: flutter_vodozemac - sha256: "54cd3790b6dfdc1afce928f8c46f7eeea9e4f8326f077400894935926f202057" - url: "https://pub.dev" - source: hosted - version: "0.3.0" - flutter_web_auth_2: - dependency: "direct main" - description: - path: flutter_web_auth_2 - ref: "3.x-without-v1" - resolved-ref: "48682f19576001e50104a602d891343850adb67f" - url: "https://github.com/ThexXTURBOXx/flutter_web_auth_2.git" - source: git - version: "3.1.2-without-v1" - flutter_web_auth_2_platform_interface: - dependency: transitive - description: - name: flutter_web_auth_2_platform_interface - sha256: e8669e262005a8354389ba2971f0fc1c36188481234ff50d013aaf993f30f739 - url: "https://pub.dev" - source: hosted - version: "3.1.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_webrtc: - dependency: "direct main" - description: - name: flutter_webrtc - sha256: b832dc76c0d1577f14aaf35e9c38d4ed7667cbc89c492b7bf4505d8d5f62e08b - url: "https://pub.dev" - source: hosted - version: "0.12.12+hotfix.1" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - geolocator: - dependency: "direct main" - description: - name: geolocator - sha256: f62bcd90459e63210bbf9c35deb6a51c521f992a78de19a1fe5c11704f9530e2 - url: "https://pub.dev" - source: hosted - version: "13.0.4" - geolocator_android: - dependency: transitive - description: - name: geolocator_android - sha256: fcb1760a50d7500deca37c9a666785c047139b5f9ee15aa5469fae7dbbe3170d - url: "https://pub.dev" - source: hosted - version: "4.6.2" - geolocator_apple: - dependency: transitive - description: - name: geolocator_apple - sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22 - url: "https://pub.dev" - source: hosted - version: "2.3.13" - geolocator_platform_interface: - dependency: transitive - description: - name: geolocator_platform_interface - sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67" - url: "https://pub.dev" - source: hosted - version: "4.2.6" - geolocator_web: - dependency: transitive - description: - name: geolocator_web - sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172 - url: "https://pub.dev" - source: hosted - version: "4.1.3" - geolocator_windows: - dependency: transitive - description: - name: geolocator_windows - sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6" - url: "https://pub.dev" - source: hosted - version: "0.2.5" - get_it: - dependency: transitive - description: - name: get_it - sha256: a4292e7cf67193f8e7c1258203104eb2a51ec8b3a04baa14695f4064c144297b - url: "https://pub.dev" - source: hosted - version: "8.2.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: f02fd7d2a4dc512fec615529824fdd217fecb3a3d3de68360293a551f21634b3 - url: "https://pub.dev" - source: hosted - version: "14.8.1" - gtk: - dependency: transitive - description: - name: gtk - sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c - url: "https://pub.dev" - source: hosted - version: "2.1.0" - handy_window: - dependency: "direct main" - description: - name: handy_window - sha256: "56b813e58a68b0ee2ab22051400b8b1f1b5cfe88b8cd32288623defb3926245a" - url: "https://pub.dev" - source: hosted - version: "0.4.0" - highlight: - dependency: transitive - description: - name: highlight - sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" - url: "https://pub.dev" - source: hosted - version: "0.7.0" - highlight_selectable: - dependency: "direct main" - description: - name: highlight_selectable - sha256: c9a9c8741bd5ba2150f1ba2c713f4ea2d6dfd6b700d66ca11675882a75c4db20 - url: "https://pub.dev" - source: hosted - version: "0.1.4" - highlighter: - dependency: transitive - description: - name: highlighter - sha256: "92180c72b9da8758e1acf39a45aa305a97dcfe2fdc8f3d1d2947c23f2772bfbc" - url: "https://pub.dev" - source: hosted - version: "0.1.1" - hive: - dependency: "direct main" - description: - name: hive - sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" - url: "https://pub.dev" - source: hosted - version: "2.2.3" - hive_flutter: - dependency: "direct main" - description: - name: hive_flutter - sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc - url: "https://pub.dev" - source: hosted - version: "1.1.0" - html: - dependency: "direct main" - description: - name: html - sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" - url: "https://pub.dev" - source: hosted - version: "0.15.6" - html_unescape: - dependency: transitive - description: - name: html_unescape - sha256: "15362d7a18f19d7b742ef8dcb811f5fd2a2df98db9f80ea393c075189e0b61e3" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - http: - dependency: "direct main" - description: - name: http - sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 - url: "https://pub.dev" - source: hosted - version: "1.5.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - image: - dependency: "direct main" - description: - name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" - url: "https://pub.dev" - source: hosted - version: "4.5.4" - image_picker: - dependency: "direct main" - description: - name: image_picker - sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - image_picker_android: - dependency: transitive - description: - name: image_picker_android - sha256: "28f3987ca0ec702d346eae1d90eda59603a2101b52f1e234ded62cff1d5cfa6e" - url: "https://pub.dev" - source: hosted - version: "0.8.13+1" - image_picker_for_web: - dependency: transitive - description: - name: image_picker_for_web - sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - image_picker_ios: - dependency: transitive - description: - name: image_picker_ios - sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e - url: "https://pub.dev" - source: hosted - version: "0.8.13" - image_picker_linux: - dependency: transitive - description: - name: image_picker_linux - sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" - url: "https://pub.dev" - source: hosted - version: "0.2.2" - image_picker_macos: - dependency: transitive - description: - name: image_picker_macos - sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04 - url: "https://pub.dev" - source: hosted - version: "0.2.2" - image_picker_platform_interface: - dependency: transitive - description: - name: image_picker_platform_interface - sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - image_picker_windows: - dependency: transitive - description: - name: image_picker_windows - sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae - url: "https://pub.dev" - source: hosted - version: "0.2.2" - import_sorter: - dependency: "direct dev" - description: - name: import_sorter - sha256: eb15738ccead84e62c31e0208ea4e3104415efcd4972b86906ca64a1187d0836 - url: "https://pub.dev" - source: hosted - version: "4.6.0" - integration_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - intl: - dependency: "direct main" - description: - name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" - source: hosted - version: "0.20.2" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - just_audio: - dependency: "direct main" - description: - name: just_audio - sha256: f978d5b4ccea08f267dae0232ec5405c1b05d3f3cd63f82097ea46c015d5c09e - url: "https://pub.dev" - source: hosted - version: "0.9.46" - just_audio_platform_interface: - dependency: transitive - description: - name: just_audio_platform_interface - sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a" - url: "https://pub.dev" - source: hosted - version: "4.6.0" - just_audio_web: - dependency: transitive - description: - name: just_audio_web - sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663" - url: "https://pub.dev" - source: hosted - version: "0.4.16" - latlong2: - dependency: "direct main" - description: - name: latlong2 - sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe" - url: "https://pub.dev" - source: hosted - version: "0.9.1" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - license_checker: - dependency: "direct dev" - description: - name: license_checker - sha256: eea27638e42bc98fd91a6a8187eb57e5617e2c3c8b313a5d51b14bec7a8685e1 - url: "https://pub.dev" - source: hosted - version: "1.6.0" - linkify: - dependency: "direct main" - description: - name: linkify - sha256: "4139ea77f4651ab9c315b577da2dd108d9aa0bd84b5d03d33323f1970c645832" - url: "https://pub.dev" - source: hosted - version: "5.0.0" - lints: - dependency: transitive - description: - name: lints - sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 - url: "https://pub.dev" - source: hosted - version: "3.0.0" - lists: - dependency: transitive - description: - name: lists - sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - logger: - dependency: transitive - description: - name: logger - sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3 - url: "https://pub.dev" - source: hosted - version: "2.6.2" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - markdown: - dependency: transitive - description: - name: markdown - sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" - url: "https://pub.dev" - source: hosted - version: "7.3.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material: - dependency: "direct main" - description: - name: material - sha256: "7f3a2edadf60e3a8771b843baff931d4b2e7205d015059c3abe315344f23dfa4" - url: "https://pub.dev" - source: hosted - version: "1.0.0+2" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - matrix: - dependency: "direct main" - description: - path: "." - ref: main - resolved-ref: "58c4cf19d010d9ae193e9df10bd1f8fdf02277b0" - url: "https://git.extera.xyz/OfficialDakari/matrix-dart-sdk.git" - source: git - version: "2.0.1" - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - mgrs_dart: - dependency: transitive - description: - name: mgrs_dart - sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7 - url: "https://pub.dev" - source: hosted - version: "2.0.0" - mime: - dependency: "direct main" - description: - name: mime - sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" - url: "https://pub.dev" - source: hosted - version: "1.0.6" - msix: - dependency: "direct dev" - description: - name: msix - sha256: f88033fcb9e0dd8de5b18897cbebbd28ea30596810f4a7c86b12b0c03ace87e5 - url: "https://pub.dev" - source: hosted - version: "3.16.12" - native_imaging: - dependency: "direct main" - description: - name: native_imaging - sha256: "93573afdcab070011d78a40fc1f69b61967f1f8485d2b81a7a2ee585a85f4c04" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - opus_caf_converter_dart: - dependency: "direct main" - description: - name: opus_caf_converter_dart - sha256: e08156066916f790a54df305e103d6dec4d853ec23147e6a02eda3c06f67ba1a - url: "https://pub.dev" - source: hosted - version: "1.0.1" - package_config: - dependency: transitive - description: - name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" - source: hosted - version: "2.2.0" - package_info_plus: - dependency: "direct main" - description: - name: package_info_plus - sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" - url: "https://pub.dev" - source: hosted - version: "8.3.1" - package_info_plus_platform_interface: - dependency: transitive - description: - name: package_info_plus_platform_interface - sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - pana: - dependency: transitive - description: - name: pana - sha256: "3fc3fe8e7a9fd4827fa4d625a423eec95d305b2bc3538a3adf7fd6c49217af97" - url: "https://pub.dev" - source: hosted - version: "0.21.45" - pasteboard: - dependency: "direct main" - description: - name: pasteboard - sha256: "1c8b6a8b3f1d12e55d4e9404433cda1b4abe66db6b17bc2d2fb5965772c04674" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - path: - dependency: "direct main" - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_provider: - dependency: "direct main" - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db" - url: "https://pub.dev" - source: hosted - version: "2.2.18" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - permission_handler: - dependency: "direct main" - description: - name: permission_handler - sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" - url: "https://pub.dev" - source: hosted - version: "11.4.0" - permission_handler_android: - dependency: transitive - description: - name: permission_handler_android - sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc - url: "https://pub.dev" - source: hosted - version: "12.1.0" - permission_handler_apple: - dependency: transitive - description: - name: permission_handler_apple - sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 - url: "https://pub.dev" - source: hosted - version: "9.4.7" - permission_handler_html: - dependency: transitive - description: - name: permission_handler_html - sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" - url: "https://pub.dev" - source: hosted - version: "0.1.3+5" - permission_handler_platform_interface: - dependency: transitive - description: - name: permission_handler_platform_interface - sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 - url: "https://pub.dev" - source: hosted - version: "4.3.0" - permission_handler_windows: - dependency: transitive - description: - name: permission_handler_windows - sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" - url: "https://pub.dev" - source: hosted - version: "0.2.1" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" - url: "https://pub.dev" - source: hosted - version: "7.0.1" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - pointer_interceptor: - dependency: transitive - description: - name: pointer_interceptor - sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" - url: "https://pub.dev" - source: hosted - version: "0.10.1+2" - pointer_interceptor_ios: - dependency: transitive - description: - name: pointer_interceptor_ios - sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917 - url: "https://pub.dev" - source: hosted - version: "0.10.1" - pointer_interceptor_platform_interface: - dependency: transitive - description: - name: pointer_interceptor_platform_interface - sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506" - url: "https://pub.dev" - source: hosted - version: "0.10.0+1" - pointer_interceptor_web: - dependency: transitive - description: - name: pointer_interceptor_web - sha256: "460b600e71de6fcea2b3d5f662c92293c049c4319e27f0829310e5a953b3ee2a" - url: "https://pub.dev" - source: hosted - version: "0.10.3" - polylabel: - dependency: transitive - description: - name: polylabel - sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" - posix: - dependency: transitive - description: - name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" - url: "https://pub.dev" - source: hosted - version: "6.0.3" - pretty_qr_code: - dependency: "direct main" - description: - name: pretty_qr_code - sha256: "2291db3f68d70a3dcd46c6bd599f30991ae4c02f27f36215fbb3f4865a609259" - url: "https://pub.dev" - source: hosted - version: "3.5.0" - process: - dependency: transitive - description: - name: process - sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" - url: "https://pub.dev" - source: hosted - version: "5.0.3" - proj4dart: - dependency: transitive - description: - name: proj4dart - sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e - url: "https://pub.dev" - source: hosted - version: "2.1.0" - provider: - dependency: "direct main" - description: - name: provider - sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" - source: hosted - version: "6.1.5+1" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" - url: "https://pub.dev" - source: hosted - version: "1.5.0" - punycode: - dependency: "direct main" - description: - name: punycode - sha256: "39b874cc1f78b94e57db17e74b3f2ba2a96e25c0bebdcc8a571614dccda0ff0c" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - qr: - dependency: transitive - description: - name: qr - sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - qr_code_scanner_plus: - dependency: "direct main" - description: - name: qr_code_scanner_plus - sha256: a0f1ac8e13299b3db2646635f252fe2ec67222b848b24ed34d11052faf080bfa - url: "https://pub.dev" - source: hosted - version: "2.0.12" - qr_image: - dependency: "direct main" - description: - name: qr_image - sha256: c3cd2ac2c6cd6b14604c97b45c477b18988b6518f72120fa04418fc54e3b0d76 - url: "https://pub.dev" - source: hosted - version: "1.0.0" - random_string: - dependency: transitive - description: - name: random_string - sha256: "03b52435aae8cbdd1056cf91bfc5bf845e9706724dd35ae2e99fa14a1ef79d02" - url: "https://pub.dev" - source: hosted - version: "2.3.1" - receive_sharing_intent: - dependency: "direct main" - description: - name: receive_sharing_intent - sha256: ec76056e4d258ad708e76d85591d933678625318e411564dcb9059048ca3a593 - url: "https://pub.dev" - source: hosted - version: "1.8.1" - record: - dependency: "direct main" - description: - name: record - sha256: "6bad72fb3ea6708d724cf8b6c97c4e236cf9f43a52259b654efeb6fd9b737f1f" - url: "https://pub.dev" - source: hosted - version: "6.1.2" - record_android: - dependency: transitive - description: - name: record_android - sha256: f05677eeed074898327f890f232f9eb49cd99d1c20d0daaf22b5612f4b2301bb - url: "https://pub.dev" - source: hosted - version: "1.4.3" - record_ios: - dependency: transitive - description: - name: record_ios - sha256: "765b42ac1be019b1674ddd809b811fc721fe5a93f7bb1da7803f0d16772fd6d7" - url: "https://pub.dev" - source: hosted - version: "1.1.4" - record_linux: - dependency: transitive - description: - name: record_linux - sha256: "235b1f1fb84e810f8149cc0c2c731d7d697f8d1c333b32cb820c449bf7bb72d8" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - record_macos: - dependency: transitive - description: - name: record_macos - sha256: "842ea4b7e95f4dd237aacffc686d1b0ff4277e3e5357865f8d28cd28bc18ed95" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - record_platform_interface: - dependency: transitive - description: - name: record_platform_interface - sha256: b0065fdf1ec28f5a634d676724d388a77e43ce7646fb049949f58c69f3fcb4ed - url: "https://pub.dev" - source: hosted - version: "1.4.0" - record_web: - dependency: transitive - description: - name: record_web - sha256: "4f0adf20c9ccafcc02d71111fd91fba1ca7b17a7453902593e5a9b25b74a5c56" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - record_windows: - dependency: transitive - description: - name: record_windows - sha256: "223258060a1d25c62bae18282c16783f28581ec19401d17e56b5205b9f039d78" - url: "https://pub.dev" - source: hosted - version: "1.0.7" - retry: - dependency: transitive - description: - name: retry - sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" - url: "https://pub.dev" - source: hosted - version: "3.1.2" - rxdart: - dependency: transitive - description: - name: rxdart - sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" - url: "https://pub.dev" - source: hosted - version: "0.28.0" - safe_url_check: - dependency: transitive - description: - name: safe_url_check - sha256: "49a3e060a7869cbafc8f4845ca1ecbbaaa53179980a32f4fdfeab1607e90f41d" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - scroll_to_index: - dependency: "direct main" - description: - name: scroll_to_index - sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176 - url: "https://pub.dev" - source: hosted - version: "3.0.1" - sdp_transform: - dependency: transitive - description: - name: sdp_transform - sha256: "73e412a5279a5c2de74001535208e20fff88f225c9a4571af0f7146202755e45" - url: "https://pub.dev" - source: hosted - version: "0.3.2" - share_plus: - dependency: "direct main" - description: - name: share_plus - sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da - url: "https://pub.dev" - source: hosted - version: "10.1.4" - share_plus_platform_interface: - dependency: transitive - description: - name: share_plus_platform_interface - sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b - url: "https://pub.dev" - source: hosted - version: "5.0.2" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" - url: "https://pub.dev" - source: hosted - version: "2.5.3" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: bd14436108211b0d4ee5038689a56d4ae3620fd72fd6036e113bf1345bc74d9e - url: "https://pub.dev" - source: hosted - version: "2.4.13" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" - url: "https://pub.dev" - source: hosted - version: "2.5.4" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.dev" - source: hosted - version: "2.4.3" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - slugify: - dependency: "direct main" - description: - name: slugify - sha256: b272501565cb28050cac2d96b7bf28a2d24c8dae359280361d124f3093d337c3 - url: "https://pub.dev" - source: hosted - version: "2.0.0" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b - url: "https://pub.dev" - source: hosted - version: "2.1.2" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" - url: "https://pub.dev" - source: hosted - version: "0.10.13" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" - sqflite: - dependency: transitive - description: - name: sqflite - sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 - url: "https://pub.dev" - source: hosted - version: "2.4.2" - sqflite_android: - dependency: transitive - description: - name: sqflite_android - sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - sqflite_common: - dependency: transitive - description: - name: sqflite_common - sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" - url: "https://pub.dev" - source: hosted - version: "2.5.6" - sqflite_common_ffi: - dependency: "direct main" - description: - name: sqflite_common_ffi - sha256: "9faa2fedc5385ef238ce772589f7718c24cdddd27419b609bb9c6f703ea27988" - url: "https://pub.dev" - source: hosted - version: "2.3.6" - sqflite_darwin: - dependency: transitive - description: - name: sqflite_darwin - sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - sqflite_platform_interface: - dependency: transitive - description: - name: sqflite_platform_interface - sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - sqlcipher_flutter_libs: - dependency: "direct main" - description: - name: sqlcipher_flutter_libs - sha256: dd1fcc74d5baf3c36ad53e2652b2d06c9f8747494a3ccde0076e88b159dfe622 - url: "https://pub.dev" - source: hosted - version: "0.6.8" - sqlite3: - dependency: transitive - description: - name: sqlite3 - sha256: "5c225083e72ea56c96d94ba1dd14fb89c8bb7731c8496ee840ab77be9bb67ae2" - url: "https://pub.dev" - source: hosted - version: "2.9.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - string_validator: - dependency: transitive - description: - name: string_validator - sha256: "50dd8ecf91db6a732f4a851eeae81ee12406eedc62d0da72f2d91a04a2d10dd8" - url: "https://pub.dev" - source: hosted - version: "0.3.0" - swipe_to_action: - dependency: "direct main" - description: - name: swipe_to_action - sha256: "05289a2bff6a0227deeff382afa1c46643d1f077e678d78f76440e153ea1ef7d" - url: "https://pub.dev" - source: hosted - version: "0.3.0" - sync_http: - dependency: transitive - description: - name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" - source: hosted - version: "0.3.1" - synchronized: - dependency: transitive - description: - name: synchronized - sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 - url: "https://pub.dev" - source: hosted - version: "3.4.0" - tar: - dependency: transitive - description: - name: tar - sha256: "22f67e2d77b51050436620b2a5de521c58ca6f0b75af1d9ab3c8cae2eae58fcd" - url: "https://pub.dev" - source: hosted - version: "1.0.5" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test: - dependency: transitive - description: - name: test - sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" - url: "https://pub.dev" - source: hosted - version: "1.26.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" - url: "https://pub.dev" - source: hosted - version: "0.7.6" - test_core: - dependency: transitive - description: - name: test_core - sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" - url: "https://pub.dev" - source: hosted - version: "0.6.11" - timezone: - dependency: transitive - description: - name: timezone - sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" - url: "https://pub.dev" - source: hosted - version: "0.9.4" - tint: - dependency: transitive - description: - name: tint - sha256: "9652d9a589f4536d5e392cf790263d120474f15da3cf1bee7f1fdb31b4de5f46" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - tor_detector_web: - dependency: "direct main" - description: - name: tor_detector_web - sha256: c4acbd6c0fecd2cd0e8fe00b1a37332422e041021a42488dfddcb3e7ec809b3f - url: "https://pub.dev" - source: hosted - version: "1.1.0" - translations_cleaner: - dependency: "direct dev" - description: - name: translations_cleaner - sha256: "060f4a8cd782e271509719741dd3540fe81ddaad49bd79e1d8fc4598299a6b84" - url: "https://pub.dev" - source: hosted - version: "0.0.5" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - unicode: - dependency: transitive - description: - name: unicode - sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" - url: "https://pub.dev" - source: hosted - version: "0.3.1" - unifiedpush: - dependency: "direct main" - description: - name: unifiedpush - sha256: "6dbed5a6305ca33f1865c7a3d814ae39476b79a2d23ca76a5708f023f405730f" - url: "https://pub.dev" - source: hosted - version: "5.0.2" - unifiedpush_android: - dependency: transitive - description: - name: unifiedpush_android - sha256: "7443dece0a850ae956514f809983eb2b39fc518c2c7d24dbfe817198bec89134" - url: "https://pub.dev" - source: hosted - version: "2.3.0" - unifiedpush_platform_interface: - dependency: transitive - description: - name: unifiedpush_platform_interface - sha256: dd588d78a8b2bfc10430e30035526e98caa543d0b7364a6344b5eb4815721c6d - url: "https://pub.dev" - source: hosted - version: "2.0.2" - unifiedpush_ui: - dependency: "direct main" - description: - name: unifiedpush_ui - sha256: cf86f0214f37debd41f25c0425c8489df85e27f9f8784fed571eb7a86d39ba11 - url: "https://pub.dev" - source: hosted - version: "0.1.0" - universal_html: - dependency: "direct main" - description: - name: universal_html - sha256: "56536254004e24d9d8cfdb7dbbf09b74cf8df96729f38a2f5c238163e3d58971" - url: "https://pub.dev" - source: hosted - version: "2.2.4" - universal_io: - dependency: transitive - description: - name: universal_io - sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" - url: "https://pub.dev" - source: hosted - version: "2.2.2" - unorm_dart: - dependency: transitive - description: - name: unorm_dart - sha256: "5b35bff83fce4d76467641438f9e867dc9bcfdb8c1694854f230579d68cd8f4b" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" - source: hosted - version: "6.3.2" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "81777b08c498a292d93ff2feead633174c386291e35612f8da438d6e92c4447e" - url: "https://pub.dev" - source: hosted - version: "6.3.20" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 - url: "https://pub.dev" - source: hosted - version: "6.3.4" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f - url: "https://pub.dev" - source: hosted - version: "3.2.3" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" - url: "https://pub.dev" - source: hosted - version: "3.1.4" - uuid: - dependency: transitive - description: - name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff - url: "https://pub.dev" - source: hosted - version: "4.5.1" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - video_compress: - dependency: "direct main" - description: - name: video_compress - sha256: "31bc5cdb9a02ba666456e5e1907393c28e6e0e972980d7d8d619a7beda0d4f20" - url: "https://pub.dev" - source: hosted - version: "3.1.4" - video_player: - dependency: "direct main" - description: - name: video_player - sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a" - url: "https://pub.dev" - source: hosted - version: "2.10.0" - video_player_android: - dependency: transitive - description: - name: video_player_android - sha256: "6cfe0b1e102522eda1e139b82bf00602181c5844fd2885340f595fb213d74842" - url: "https://pub.dev" - source: hosted - version: "2.8.14" - video_player_avfoundation: - dependency: transitive - description: - name: video_player_avfoundation - sha256: f9a780aac57802b2892f93787e5ea53b5f43cc57dc107bee9436458365be71cd - url: "https://pub.dev" - source: hosted - version: "2.8.4" - video_player_platform_interface: - dependency: transitive - description: - name: video_player_platform_interface - sha256: cf2a1d29a284db648fd66cbd18aacc157f9862d77d2cc790f6f9678a46c1db5a - url: "https://pub.dev" - source: hosted - version: "6.4.0" - video_player_web: - dependency: transitive - description: - name: video_player_web - sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 - url: "https://pub.dev" - source: hosted - version: "15.0.0" - vodozemac: - dependency: "direct main" - description: - name: vodozemac - sha256: "95cac62ffab94db99e134c8f9aac198f8131a4eed0bed76a6cfc9c72add229b9" - url: "https://pub.dev" - source: hosted - version: "0.3.0" - wakelock_plus: - dependency: "direct main" - description: - name: wakelock_plus - sha256: "61713aa82b7f85c21c9f4cd0a148abd75f38a74ec645fcb1e446f882c82fd09b" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - wakelock_plus_platform_interface: - dependency: transitive - description: - name: wakelock_plus_platform_interface - sha256: "036deb14cd62f558ca3b73006d52ce049fabcdcb2eddfe0bf0fe4e8a943b5cf2" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" - url: "https://pub.dev" - source: hosted - version: "1.1.4" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webdriver: - dependency: transitive - description: - name: webdriver - sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - webrtc_interface: - dependency: "direct main" - description: - name: webrtc_interface - sha256: "2e604a31703ad26781782fb14fa8a4ee621154ee2c513d2b9938e486fa695233" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - win32: - dependency: "direct overridden" - description: - name: win32 - sha256: "015002c060f1ae9f41a818f2d5640389cc05283e368be19dc8d77cecb43c40c9" - url: "https://pub.dev" - source: hosted - version: "5.5.3" - win32_registry: - dependency: transitive - description: - name: win32_registry - sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" - url: "https://pub.dev" - source: hosted - version: "1.1.5" - window_to_front: - dependency: transitive - description: - name: window_to_front - sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee" - url: "https://pub.dev" - source: hosted - version: "0.0.3" - wkt_parser: - dependency: transitive - description: - name: wkt_parser - sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xml: - dependency: transitive - description: - name: xml - sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.dev" - source: hosted - version: "6.6.1" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" -sdks: - dart: ">=3.8.0 <4.0.0" - flutter: ">=3.32.0" diff --git a/pubspec.yaml b/pubspec.yaml index f3d5167..cd0cccd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,8 +26,8 @@ dependencies: emoji_picker_flutter: ^3.1.0 emojis: ^0.9.9 #fcm_shared_isolate: ^0.2.0 - file_picker: ^10.2.1 - file_selector: ^1.0.3 + file_picker: ^10.3.3 + file_selector: ^1.0.4 flutter: sdk: flutter flutter_cache_manager: ^3.4.1 @@ -104,7 +104,7 @@ dependencies: dev_dependencies: flutter_lints: ^3.0.0 - flutter_native_splash: ^2.0.3+1 + flutter_native_splash: ^2.4.6 flutter_test: sdk: flutter import_sorter: ^4.6.0