diff --git a/core/i18n/src/main/res/values-th/strings.xml b/core/i18n/src/main/res/values-th/strings.xml index fe0df3d75..0557ba4f8 100644 --- a/core/i18n/src/main/res/values-th/strings.xml +++ b/core/i18n/src/main/res/values-th/strings.xml @@ -115,7 +115,7 @@ หาปฏิทินไม่เจอหรือ\? คุณต้องอนุญาตให้แอปเข้าถึงปฏิทินเพื่อแสดงนัดหมายและกิจกรรมที่นี่ คุณต้องอนุญาตให้แอปเข้าถึงรายชื่อผู้ติดต่อเพื่อค้นหาในรายชื่อผู้ติดต่อ - กำหนดให้แอป %1$s เป็นตัวใช้งานเริ่มต้นเพื่อค้นหาทางลัดแอป + กำหนดให้แอป %1$s เป็นลอนเชอร์เริ่มต้นเพื่อค้นหาทางลัดแอป อนุญาต ลักษณะ มืด @@ -215,7 +215,7 @@ ค้นหา ไฟล์เก็บข้อมูลกิจกรรมแอป รายการโปรด - การค้นหา แท็ก สิ่งที่ถูกซ่อน + การค้นหา แท็ก ผลการค้นหาที่ถูกตัดออก ไฟล์ ปฏิทิน ทางลัดแอป @@ -236,9 +236,9 @@ สี เปิดคีย์บอร์ด เปิดแอปเมื่อกด Enter - ซ่อนผลการค้นหา - จัดการแอปและผลการค้นหาที่ถูกซ่อน - แสดงปุ่มที่เปิดเผยผลการค้นหาที่ซ่อนไว้ + ผลการค้นหาที่ถูกตัดออก + จัดการแอปและผลการค้นหาที่ถูกตัดออก + แสดงปุ่มเผยผลการค้นหาที่ถูกตัดออก แท็ก จัดการแท็ก และสิ่งที่ถูกแท็ก ลิงก์วิกิพีเดีย @@ -261,7 +261,7 @@ งาน ไม่มีสิ่งที่มีแท็กนี้ จำนวนแถว - ควิกแอ็กชั่น + ควิกแอกชัน โทร ส่งข้อความ ส่งอีเมล @@ -294,10 +294,10 @@ แตะสองครั้งติดกัน ปุ่มหน้าแรก/ท่าทางการสัมผัส ไม่ต้องทำอะไร - เปิดการค้นหา + การค้นหา / ลิ้นชักรวมแอป ปิดหน้าจอ - แสดงเมนูเปิดปิดเครื่อง - เปิดแอปที่เพิ่งถูกใช้ + เมนูเปิดปิดเครื่อง + แอปที่เปิดล่าสุด เปลี่ยนช้า เปลี่ยนปานกลาง เปลี่ยนเร็ว @@ -360,17 +360,17 @@ https://www.youtube.com/results\?search_query=${1} ข้อมูลสำรอง %1$s Google Play - ลบรายการที่เสียและไม่จำเป็นออกจากฐานข้อมูลของแอปหน้าแรก + ลบรายการที่เสียและไม่จำเป็นออกจากฐานข้อมูลของลอนเชอร์ https://play.google.com/store/search\?q=${1} - ส่งออกและนำเข้าข้อมูลแอปหน้าแรก - ส่งออกการตั้งค่าและข้อมูลแอปหน้าแรก - จำเป็นต้องเปิดใช้งานสิทธิ์การเข้าถึงของแอปหน้าแรกจึงจะสามารถดำเนินการนี้ได้ + ส่งออกและนำเข้าข้อมูลลอนเชอร์ + ส่งออกการตั้งค่าและข้อมูลลอนเชอร์ + จำเป็นต้องเปิดใช้งานสิทธิ์การเข้าถึงของลอนเชอร์จึงจะสามารถดำเนินการนี้ได้ เข้ารหัสแบบเปอร์เซ็นต์ - การดำเนินการนี้ต้องการสิทธิ์การเข้าถึงของแอปหน้าแรก + การดำเนินการนี้ต้องการสิทธิ์การเข้าถึงของลอนเชอร์ application/x-www-form-urlencoded แก้ไขวิดเจ็ต - ไม่สามารถอ่านไฟล์โน้ตต้นฉบับได้ ข้อมูลสำเนาถูกกู้คืนมาจากพื้นที่จัดเก็บภายในของแอปหน้าแรก ถ้าคุณแก้ไขโน้ต ไฟล์โน้ตต้นฉบับอาจโดนเขียนทับ - ไม่สามารถเขียนโน้ตไปยังไฟล์ต้นฉบับได้ บันทึกข้อมูลสำเนาไปยังพื้นที่จัดเก็บภายในของแอปหน้าแรกแล้ว + ไม่สามารถอ่านไฟล์โน้ตต้นฉบับได้ ข้อมูลสำเนาถูกกู้คืนมาจากพื้นที่จัดเก็บภายในของลอนเชอร์ ถ้าคุณแก้ไขโน้ต ไฟล์โน้ตต้นฉบับอาจโดนเขียนทับ + ไม่สามารถเขียนโน้ตไปยังไฟล์ต้นฉบับได้ บันทึกข้อมูลสำเนาไปยังพื้นที่จัดเก็บภายในของลอนเชอร์แล้ว ลิงก์ %1$s เพิ่มวิดเจ็ต ปักหมุดไปยังรายการโปรด @@ -456,7 +456,7 @@ คุณต้องอนุญาตให้แอปเข้าถึงรายชื่อผู้ติดต่อเพื่อค้นหาผู้ติดต่อ ดูและส่งออกไฟล์เก็บข้อมูลกิจกรรมแอป คุณต้องอนุญาตให้แอปเข้าถึงปฏิทินเพื่อค้นหาปฏิทิน - คุณต้องกำหนดให้แอป %1$s เป็นตัวใช้งานเริ่มต้นจึงจะค้นหาทางลัดแอปได้ + คุณต้องกำหนดให้แอป %1$s เป็นลอนเชอร์เริ่มต้นจึงจะค้นหาทางลัดแอปได้ แสดงสิ่งที่ถูกปักหมุดและสิ่งที่ถูกใช้งานบ่อยข้างบนลิ้นชักแอป แสดงปุ่มสำหรับการเพิ่ม ลบ และจัดเรียงวิดเจ็ต คุณต้องอนุญาตให้แอปเข้าถึงพื้นที่จัดเก็บข้อมูลภายนอกเพื่อค้นหาไฟล์บนอุปกรณ์นี้ @@ -473,7 +473,7 @@ สภาพอากาศ คุณต้องอนุญาตให้แอปเข้าถึงพื้นที่จัดเก็บข้อมูลเพื่อค้นหาไฟล์บนอุปกรณ์นี้ คำนวณและดำเนินการทางคณิตศาสตร์ - กำหนดให้แอป %1$s เป็นตัวใช้งานเริ่มต้นเพื่อสร้างทางลัด + กำหนดให้แอป %1$s เป็นลอนเชอร์เริ่มต้นเพื่อสร้างทางลัด ดาวน์โหลดอัตราแรกเปลี่ยนเพื่อแปลงสกุลเงินเป็นระยะๆ แสดงตัวอย่างของเว็บไซต์ถ้าคำค้นหาเป็นลิงก์ ตัวควบคุมสื่อ @@ -490,12 +490,12 @@ ข้อมูลสำรองนี้ถูกสร้างโดย %1$s คนละเวอร์ชั่น จึงไม่สามารถกู้คืนด้วยเวอร์ชั่นปัจจุบันได้ แสดงคีย์บอร์ดอัตโนมัติเมื่อเปิดลิ้นชักรวมแอป ข้อมูลสำรองนี้ถูกสร้างโดย %1$s คนละเวอร์ชั่น ข้อมูลบางส่วนอาจไม่ถูกกู้คืนอย่างถูกต้อง - เปิดสิ่งที่ถูกไฮไลต์หรือควิกแอ็กชั่นเมื่อแตะ \"ไป\" + เปิดสิ่งที่ถูกไฮไลต์หรือควิกแอกชันเมื่อแตะ \"ไป\" รายการโปรด แสดงปุ่มเลิกซ่อน สิ่งที่ถูกปักหมุดไว้และสิ่งที่ถูกใช้บ่อยจะถูกแสดงที่นี่ แสดงในรายการโปรด - ปรับแต่งควิกแอ็กชั่น + ปรับแต่งควิกแอกชัน ตั้งปลุก เริ่มจับเวลา เขียนกำหนดการกิจกรรม @@ -518,8 +518,8 @@ ปัดขวา แตะค้าง เปิดแอป - เปิดแผงการแจ้งเตือน - เปิดการตั้งค่าลัด + การแจ้งเตือน + การตั้งค่าลัด คุณได้ทำท่าทางการสัมผัสแบบ \"%1$s\" ซึ่งถูกกำหนดไว้ว่าให้ทำ \"%2$s\" แต่ไม่สามารถดำเนินการได้เพราะเหตุผลต่อไปนี้: ความเร็วในการเปลี่ยนแปลงลำดับ การ์ดพื้นหลัง @@ -530,7 +530,7 @@ ลิงก์ใหม่ มีความขัดแย้งของข้อมูล ไฟล์ที่ถูกลิงก์มีข้อมูลอยู่แต่เนื้อหาของไฟล์ไม่ตรงกับเวอร์ชั่นล่าสุดที่ถูกบันทึกในโน้ตนี้ คุณต้องการเก็บเวอร์ชั่นใดไว้\? - คุณต้องการลบชุดสี %1$s ใช่หรือไม่? + คุณต้องการลบโทนสี %1$s ใช่หรือไม่? ธีม %1$s ไม่สามารถอ่านไฟล์ที่เลือกไว้ได้ กรุณาตรวจสอบว่าคุณได้เลือกไฟล์ธีมที่ถูกต้อง (*.kvtheme) และข้อมูลไฟล์ไม่เสียหาย ความมัว @@ -541,7 +541,7 @@ เข้าถึงไม่ได้ การจัดตำแหน่ง ด้านล่าง - ไม่สามารถเข้าถึงทางลัดนี้ได้ เนื่องจาก %1$s ไม่ได้ถูกตั้งเป็นแอปหน้าแรกริ่มต้น + ไม่สามารถเข้าถึงทางลัดนี้ได้ เนื่องจาก %1$s ไม่ได้ถูกตั้งเป็นลอนเชอร์เริ่มต้น ส่วนไดนามิก ปลั๊กอิน จัดการส่วนเสริมที่ติดตั้งไว้ @@ -587,7 +587,7 @@ ขอบเขตการค้นหา ค้นหาร้านค้าและสถานที่อื่นๆในพื้นที่ใกล้เคียง แผนที่ - ปรับสีของแผนที่ตามโทนสีของแอปหน้าแรก + ปรับสีของแผนที่ตามโทนสีของลอนเชอร์ คุณต้องตั้งค่าปลั๊กอินนี้ก่อน พายุฝนฟ้าคะนอง สถานที่ @@ -833,12 +833,12 @@ (ไม่มีชื่อ) ความโปร่งใส คุณต้องการลบชุดความโปร่งใส %1$s ใช่หรือไม่? - การจัดตัวอักษร - คุณต้องการลบชุดการจัดตัวอักษร %1$s ใช่หรือไม่? - ชุดแบบอักษร + ฟอนต์ + คุณต้องการลบชุดฟอนต์ %1$s ใช่หรือไม่? + รูปแบบฟอนต์ ค่าเริ่มต้นของอุปกรณ์ ชุดแบบอักษรของอุปกรณ์ - ชุดแบบอักษรเริ่มต้นสำหรับหัวเรื่อง + ฟอนต์เริ่มต้นสำหรับหัวเรื่อง ทั่วไป โปร่งใส สีทึบ @@ -850,4 +850,79 @@ แฮกเกอร์สเปซ ร้านขายเครื่องเขียน แถวในด็อค + ออก + ยูวี %1$d + แอป + โทนสีใหม่ + ชุดรูปร่าง + ชุดฟอนต์ใหม่ + ชุดความโปร่งใสใหม่ + เปิดใช้งานแล้ว + ติดตั้งแล้ว + จัดการโดย Smartspacer + แสดงไว้เสมอ + แสดงเมื่อเหลือน้อยหรือกำลังชาร์จอยู่ + ไม่แสดง + แอป + แสดงแอปทั้งหมดเมื่อยังไม่ได้พิมพ์สิ่งใดในแถบการค้นหา + แสดงข้อมูลแอป + แสดงเวอร์ชันและชื่อแพ็กเกจของแอปในเมนูกดค้าง + การตั้งค่าสกุลเงิน + Smartspacer + Smartspacer คือแอปเสรีและโอเพนซอร์สสำหรับวิดเจ็ตข้อมูลโดยย่อ (At a Glance) คุณสามารถติดตั้งแอป Smartspacer เพื่อนำไปใช้ในโซนไดนามิกของวิดเจ็ตนาฬิกาได้ + เปิดใช้งานการเชื่อมต่อกับ Smartspacer + เปิด Smartspacer + ฟีด + ผู้ให้บริการฟีด + ปัดไปทางขวาบนหน้าจอหลักเพื่อเปิดฟีด + ยังไม่ไ่ด้ติดตั้งผู้ให้บริการฟีดใด + พื้นที่ส่วนตัว + ล็อกพื้นที่ส่วนตัว + ปลดล็อกพื้นที่ส่วนตัว + ควิกแอกชันใหม่ + แก้ไขควิกแอกชัน + เว้นชื่อว่างไว้ไม่ได้ + ไอคอน + อีโมจิ + หน้าต่างๆของลอนเชอร์ + แอกชันระบบ + ทางลัดและแอปต่างๆ + หน้าวิดเจ็ตใหม่ + ว่าง + วิดเจ็ต (%1$d) + เลือกแอปหรือทางลัด + ฟีด + เพิ่มรูปแบบฟอนต์ + ลบรูปแบบฟอนต์นี้ + ภาษาและภูมิภาค + ภาษา หน่วยวัด และรูปแบบเวลา + ภาษา + ค่าเริ่มต้นของระบบ + ปิดใช้งาน + การพูดถึงตัวคุณ + กลางๆ + เพศหญิง + เพศชาย + ระบบการวัด + เมตริก + สหราชอาณาจักร + สหรัฐอเมริกา + การทับศัพท์ที่ต้องการใช้ + อัตโนมัติ + ระบบปฏิทิน + ปฏิทินหลัก + ปฏิทินรอง + สกุลเงิน + เพิ่มสกุลเงิน + เลือกแท็ก + แท็กใหม่ + แก้ไขแท็ก + ออกโดยไม่บันทึกใช่หรือไม่ + กข + สยาม + ไทย + กรุงเทพฯ + ถนนจตุรทิศ + นายสมศักดิ์ ภูมิใจ\nหมายเลขบัตร 124790 + สนับสนุนการพัฒนา diff --git a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt index db995b75a..7c4e61d12 100644 --- a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt +++ b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt @@ -23,6 +23,8 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted @@ -115,62 +117,34 @@ internal class AppShortcutRepositoryImpl( return flags } + private class NormalizedShortcut( + val info: ShortcutInfo, + val normalizedLabels: List, + ) + override fun search(query: String, allowNetwork: Boolean): Flow> { if (query.length < 3) { return flowOf(persistentListOf()) } val normalizedQuery = stringNormalizer.normalize(query) + return rawShortcuts.map { shortcuts -> + val filtered = shortcuts.mapIndexedNotNull { index, normalized -> + if (index % 8 == 0) currentCoroutineContext().ensureActive() - return combine( - listOf( - settings.enabled, - permissionsManager.hasPermission(PermissionGroup.AppShortcuts), - shortcutChangeEmitter - ) - ) { it } - .map { (enabled, perm, _) -> - enabled as Boolean - perm as Boolean - - if (enabled && perm) { - val launcherApps = - context.getSystemService() ?: return@map persistentListOf() - - - val shortcutQuery = LauncherApps.ShortcutQuery() - shortcutQuery.setQueryFlags( - LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED or - LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC or - LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST or - LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED or - LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER - ) - val shortcuts = launcherApps.getShortcuts(shortcutQuery, Process.myUserHandle()) - ?.mapNotNull { - val score = ResultScore.from( - query = normalizedQuery, - primaryFields = listOfNotNull( - it.longLabel?.toString() - ?.let { stringNormalizer.normalize(it) }, - it.shortLabel?.toString() - ?.let { stringNormalizer.normalize(it) }, - ) - ) - if (score.score < 0.8f) return@mapNotNull null - LauncherShortcut( - context, - it, - score - ) - } ?: emptyList() - - shortcuts.toImmutableList() - - } else { - persistentListOf() - } - }.flowOn(Dispatchers.Default) + val score = ResultScore.from( + query = normalizedQuery, + primaryFields = normalized.normalizedLabels, + ) + if (score.score < 0.8f) return@mapIndexedNotNull null + LauncherShortcut( + context, + normalized.info, + score + ) + }.toImmutableList() + filtered + }.flowOn(Dispatchers.Default) } private val shortcutChangeEmitter = callbackFlow { @@ -219,6 +193,45 @@ internal class AppShortcutRepositoryImpl( } }.shareIn(scope, SharingStarted.WhileSubscribed(500), 1) + private val rawShortcuts: Flow> = combine( + listOf( + settings.enabled, + permissionsManager.hasPermission(PermissionGroup.AppShortcuts), + shortcutChangeEmitter + ) + ) { it } + .map { (enabled, perm, _) -> + enabled as Boolean + perm as Boolean + + if (!enabled || !perm) return@map emptyList() + + val launcherApps = + context.getSystemService() ?: return@map emptyList() + + val shortcutQuery = LauncherApps.ShortcutQuery() + shortcutQuery.setQueryFlags( + LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED or + LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC or + LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST or + LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED or + LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER + ) + val result = launcherApps.getShortcuts(shortcutQuery, Process.myUserHandle()) ?: emptyList() + val normalized = result.map { + NormalizedShortcut( + info = it, + normalizedLabels = listOfNotNull( + it.longLabel?.toString()?.let { l -> stringNormalizer.normalize(l) }, + it.shortLabel?.toString()?.let { l -> stringNormalizer.normalize(l) }, + ) + ) + } + normalized + } + .flowOn(Dispatchers.Default) + .shareIn(scope, SharingStarted.Eagerly, replay = 1) + override suspend fun getShortcutsConfigActivities(): List { val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps if (!launcherApps.hasShortcutHostPermission()) return emptyList() diff --git a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt index e69a06c42..edd4b036b 100644 --- a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt +++ b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt @@ -8,7 +8,7 @@ import org.koin.core.qualifier.named import org.koin.dsl.module val appShortcutsModule = module { - factory { AppShortcutRepositoryImpl(androidContext(), get(), get(), get(), get()) } + single { AppShortcutRepositoryImpl(androidContext(), get(), get(), get(), get()) } factory>(named()) { get() } factory(named(LauncherShortcut.Domain)) { LauncherShortcutDeserializer(androidContext()) } factory(named(LegacyShortcut.Domain)) { LegacyShortcutDeserializer(androidContext()) }