From 12fa5b7746f00dbea0888aaaebf0027b68aff484 Mon Sep 17 00:00:00 2001 From: MickeyMoz Date: Tue, 1 Jun 2021 16:54:56 +0000 Subject: [PATCH 001/500] Update Android Components version to 90.0.20210531190346. --- buildSrc/src/main/java/AndroidComponents.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/java/AndroidComponents.kt b/buildSrc/src/main/java/AndroidComponents.kt index ca228a3cb073..115d839e501b 100644 --- a/buildSrc/src/main/java/AndroidComponents.kt +++ b/buildSrc/src/main/java/AndroidComponents.kt @@ -3,5 +3,5 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ object AndroidComponents { - const val VERSION = "90.0.20210531143146" + const val VERSION = "90.0.20210531190346" } From 1bfb05129bf7c62af8fa4ae66ce11996172f38bf Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Tue, 1 Jun 2021 14:18:30 -0400 Subject: [PATCH 002/500] Update version.txt to 91.0.0-beta.1 (#19749) --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 645c46766446..0ec584229cdd 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -89.0.0-beta.1 +91.0.0-beta.1 From 9fb436664631e2fb43582b7feb4ebed6cc1a5ece Mon Sep 17 00:00:00 2001 From: Michael Comella Date: Wed, 19 May 2021 09:45:33 -0700 Subject: [PATCH 003/500] =?UTF-8?q?For=20perf-frontend-issues#208:=20add?= =?UTF-8?q?=20nav=5Fstart=20test=20to=20measure=E2=80=A6=20script.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/measure_time_to_first_frame.py | 94 +++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/tools/measure_time_to_first_frame.py b/tools/measure_time_to_first_frame.py index 0056becde346..5e541ac4d887 100755 --- a/tools/measure_time_to_first_frame.py +++ b/tools/measure_time_to_first_frame.py @@ -4,7 +4,9 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import argparse +import datetime import os +import re import subprocess import time from pprint import pprint @@ -29,6 +31,11 @@ 'debug': 'org.mozilla.fenix.debug' } +TEST_COLD_MAIN_FF = 'cold_main_first_frame' +TEST_COLD_VIEW_FF = 'cold_view_first_frame' +TEST_COLD_VIEW_NAV_START = 'cold_view_nav_start' +TESTS = [TEST_COLD_MAIN_FF, TEST_COLD_VIEW_FF, TEST_COLD_VIEW_NAV_START] + def parse_args(): parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawDescriptionHelpFormatter) @@ -36,13 +43,14 @@ def parse_args(): "release_channel", choices=['nightly', 'beta', 'release', 'debug'], help="the release channel to measure" ) parser.add_argument( - "startup_type", choices=['cold_main', 'cold_view'], help="the type of start up to measure. see https://wiki.mozilla.org/Performance/Fenix#Terminology for descriptions of cold/warm/hot and main/view" + "test_name", choices=TESTS, help="the start up test to run; see https://wiki.mozilla.org/Performance/Fenix#Terminology for descriptions of cold/warm/hot and main/view" ) - parser.add_argument("path", help="the path to save the measurement results; will be overwritten") + parser.add_argument("path", help="the path to save the measurement results; will abort if file exists") parser.add_argument("-c", "--iter-count", default=DEFAULT_ITER_COUNT, type=int, help="the number of iterations to run. defaults to {}".format(DEFAULT_ITER_COUNT)) parser.add_argument("-f", "--force", action="store_true", help="overwrite the given path rather than stopping on file existence") + return parser.parse_args() @@ -77,23 +85,22 @@ def disable_startup_profiling(): subprocess.run(args, check=True) -def get_start_cmd(startup_type, pkg_id): +def get_start_cmd(test_name, pkg_id): args_prefix = get_activity_manager_args() + ['start-activity', '-W', '-n'] - if startup_type == 'cold_main': + if test_name == TEST_COLD_MAIN_FF: cmd = args_prefix + ['{}/.App'.format(pkg_id)] - elif startup_type == 'cold_view': + elif test_name == TEST_COLD_VIEW_FF or test_name == TEST_COLD_VIEW_NAV_START: pkg_activity = '{}/org.mozilla.fenix.IntentReceiverActivity'.format(pkg_id) cmd = args_prefix + [ pkg_activity, '-d', 'https://example.com', '-a', 'android.intent.action.VIEW' ] - else: - raise Exception('Should never happen (if argparse is set up correctly') + else: raise NotImplementedError('method unexpectedly undefined for test_name {}'.format(test_name)) return cmd -def measure(pkg_id, start_cmd_args, iter_count): +def measure(test_name, pkg_id, start_cmd_args, iter_count): # Startup profiling may accidentally be left enabled and throw off the results. # To prevent this, we disable it. disable_startup_profiling() @@ -105,17 +112,33 @@ def measure(pkg_id, start_cmd_args, iter_count): time.sleep(5) # To hopefully reach visual completeness. measurements = [] - for i in range(0, iter_count): + for _ in range(0, iter_count): force_stop(pkg_id) time.sleep(1) + + # This is only necessary for nav start tests (to ensure logcat only contains the result from the current run). + # However, it's not known to be disruptive to other tests (to first frame) so we leave it in. + subprocess.run(['adb', 'logcat', '-c'], check=True) + proc = subprocess.run(start_cmd_args, check=True, capture_output=True) # expected to wait for app to start. - measurements.append(get_measurement_from_stdout(proc.stdout)) + measurements.append(get_measurement(test_name, pkg_id, proc.stdout)) + return measurements -def get_measurement_from_stdout(stdout): - # Sample input: - # +def get_measurement(test_name, pkg_id, stdout): + if test_name == TEST_COLD_MAIN_FF or test_name == TEST_COLD_VIEW_FF: + measurement = get_measurement_from_am_start_log(stdout) + elif test_name == TEST_COLD_VIEW_NAV_START: + time.sleep(3) # We must sleep until the navigation start event occurs. + proc = subprocess.run(['adb', 'logcat', '-d'], check=True, capture_output=True) + measurement = get_measurement_from_nav_start_logcat(pkg_id, proc.stdout) + else: raise NotImplementedError('method unexpectedly undefined for test_name {}'.format(test_name)) + return measurement + + +def get_measurement_from_am_start_log(stdout): + # Sample output: # Starting: Intent { cmp=org.mozilla.fenix/.App } # Status: ok # Activity: org.mozilla.fenix/.App @@ -133,6 +156,45 @@ def get_measurement_from_stdout(stdout): return duration +def get_measurement_from_nav_start_logcat(pkg_id, logcat_bytes): + # Relevant lines: + # 05-18 14:32:47.366 1759 6003 I ActivityManager: START u0 {act=android.intent.action.VIEW dat=https://example.com/... typ=text/html flg=0x10000000 cmp=org.mozilla.fenix/.IntentReceiverActivity} from uid 2000 + # 05-18 14:32:47.402 1759 6003 I ActivityManager: Start proc 9007:org.mozilla.fenix/u0a170 for activity org.mozilla.fenix/.IntentReceiverActivity + # 05-18 14:32:50.809 9007 9007 I GeckoSession: handleMessage GeckoView:PageStart uri= + # 05-18 14:32:50.821 9007 9007 I GeckoSession: handleMessage GeckoView:PageStop uri=null + def line_to_datetime(line): + date_str = ' '.join(line.split(' ')[:2]) # e.g. "05-18 14:32:47.366" + # strptime needs microseconds. logcat outputs millis so we append zeroes + date_str_with_micros = date_str + '000' + return datetime.datetime.strptime(date_str_with_micros, '%m-%d %H:%M:%S.%f') + + def get_proc_start_datetime(): + # This regex may not work on older versions of Android: we don't care + # yet because supporting older versions isn't in our requirements. + proc_start_re = re.compile('ActivityManager: Start proc \d+:{}/'.format(pkg_id)) + proc_start_lines = [line for line in lines if proc_start_re.search(line)] + assert len(proc_start_lines) == 1 + return line_to_datetime(proc_start_lines[0]) + + def get_page_start_datetime(): + page_start_re = re.compile('GeckoSession: handleMessage GeckoView:PageStart uri=') + page_start_lines = [line for line in lines if page_start_re.search(line)] + assert len(page_start_lines) == 2 # One for about:blank & one for target URL. + return line_to_datetime(page_start_lines[1]) # 2nd PageStart is for target URL. + + logcat = logcat_bytes.decode('UTF-8') # Easier to work with and must for strptime. + lines = logcat.split('\n') + + # We measure the time from process start, rather than the earlier START + # activity line, because I assume we have no control over the duration + # before our process starts. If we wanted to put in more time, we could + # double-check this assumption by seeing what values `am start -W` returns + # compared to the time stamps. + elapsed_seconds = (get_page_start_datetime() - get_proc_start_datetime()).total_seconds() # values < 1s are expressed in decimal. + elapsed_millis = round(elapsed_seconds * 1000) + return elapsed_millis + + def save_measurements(path, measurements): with open(path, 'w') as f: for measurement in measurements: @@ -145,11 +207,11 @@ def main(): # Exceptions and script piping like these are why we prefer mozperftest. :) print("Clear the onboarding experience manually, if it's desired and you haven't already done so.") - print("\nYou can use this script to find the average from the results file: https://github.com/mozilla-mobile/perf-tools/blob/9dd8bf1ea0ea8b2663e21d341a1572c5249c513d/average_times.py") + print("\nYou can use this script to find the average from the results file: https://github.com/mozilla-mobile/perf-tools/blob/master/analyze_durations.py") pkg_id = get_package_id(args.release_channel) - start_cmd = get_start_cmd(args.startup_type, pkg_id) - measurements = measure(pkg_id, start_cmd, args.iter_count) + start_cmd = get_start_cmd(args.test_name, pkg_id) + measurements = measure(args.test_name, pkg_id, start_cmd, args.iter_count) save_measurements(args.path, measurements) From 18f0931d2eab74e8154b098246d42cefdbb00268 Mon Sep 17 00:00:00 2001 From: Michael Comella Date: Tue, 25 May 2021 17:16:16 -0700 Subject: [PATCH 004/500] For perf-frontend-issues#208: use CHANNEL_TO_PKG directly. --- tools/measure_time_to_first_frame.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tools/measure_time_to_first_frame.py b/tools/measure_time_to_first_frame.py index 5e541ac4d887..ea54747b1cc8 100755 --- a/tools/measure_time_to_first_frame.py +++ b/tools/measure_time_to_first_frame.py @@ -40,7 +40,7 @@ def parse_args(): parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( - "release_channel", choices=['nightly', 'beta', 'release', 'debug'], help="the release channel to measure" + "release_channel", choices=CHANNEL_TO_PKG.keys(), help="the release channel to measure" ) parser.add_argument( "test_name", choices=TESTS, help="the start up test to run; see https://wiki.mozilla.org/Performance/Fenix#Terminology for descriptions of cold/warm/hot and main/view" @@ -61,13 +61,6 @@ def validate_args(args): raise Exception("Given `path` unexpectedly exists: pick a new path or use --force to overwrite.") -def get_package_id(release_channel): - package_id = CHANNEL_TO_PKG.get(release_channel) - if not package_id: - raise Exception('this should never happen: this should be validated by argparse') - return package_id - - def get_activity_manager_args(): return ['adb', 'shell', 'am'] @@ -209,7 +202,7 @@ def main(): print("Clear the onboarding experience manually, if it's desired and you haven't already done so.") print("\nYou can use this script to find the average from the results file: https://github.com/mozilla-mobile/perf-tools/blob/master/analyze_durations.py") - pkg_id = get_package_id(args.release_channel) + pkg_id = CHANNEL_TO_PKG[args.release_channel] start_cmd = get_start_cmd(args.test_name, pkg_id) measurements = measure(args.test_name, pkg_id, start_cmd, args.iter_count) save_measurements(args.path, measurements) From 23068cd2f7b5758730b265c70a76f1cc053a2486 Mon Sep 17 00:00:00 2001 From: Michael Comella Date: Tue, 25 May 2021 19:15:10 -0700 Subject: [PATCH 005/500] For perf-frontend-issues#208: clean up help text. --- tools/measure_time_to_first_frame.py | 47 ++++++++++++++++++---------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/tools/measure_time_to_first_frame.py b/tools/measure_time_to_first_frame.py index ea54747b1cc8..608c5c14b73e 100755 --- a/tools/measure_time_to_first_frame.py +++ b/tools/measure_time_to_first_frame.py @@ -9,17 +9,16 @@ import re import subprocess import time -from pprint import pprint -DESC = """Measures the duration from process start until the first frame is drawn -using the "TotalTime:" field from `adb shell am start -W`. This script is a python -reimplementation of https://medium.com/androiddevelopers/testing-app-startup-performance-36169c27ee55 -with additional functionality. +DESC = """Measures start up durations using multiple methodologies. -IMPORTANT: this method does not provide a complete picture of start up. Using -./mach perftest (or the deprecated FNPRMS) is the preferred approach because those -provide more comprehensive views of start up. However, this is useful for lightweight -testing if you know exactly what you're looking for. +IMPORTANT: each methodology provides a different picture of start up. If you're +not sure which one to use, please ask the perf team! + +IMPORTANT: some tests require manual test set up! Read the output carefully. + +This system is temporary until mozperftest is ready (e.g. less noisy). As such, +we try to keep this simple and avoid implementing all the things they do. """ DEFAULT_ITER_COUNT = 25 @@ -38,13 +37,22 @@ def parse_args(): - parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawDescriptionHelpFormatter) + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument( "release_channel", choices=CHANNEL_TO_PKG.keys(), help="the release channel to measure" ) parser.add_argument( - "test_name", choices=TESTS, help="the start up test to run; see https://wiki.mozilla.org/Performance/Fenix#Terminology for descriptions of cold/warm/hot and main/view" - ) + "test_name", choices=TESTS, help="""the measurement methodology to use. Options: +- {cold_main_ff}: click the app icon & get duration to first frame from 'am start -W' +- {cold_view_ff}: send a VIEW intent & get duration to first frame from 'am start -W' +- {cold_view_nav_start}: send a VIEW intent & get duration from logcat: START proc to PageStart + +Measurements to first frame are a reimplementation of +https://medium.com/androiddevelopers/testing-app-startup-performance-36169c27ee55 + +See https://wiki.mozilla.org/Performance/Fenix#Terminology for descriptions of cold/warm/hot and main/view""".format( + cold_main_ff=TEST_COLD_MAIN_FF, cold_view_ff=TEST_COLD_VIEW_FF, cold_view_nav_start=TEST_COLD_VIEW_NAV_START +)) parser.add_argument("path", help="the path to save the measurement results; will abort if file exists") parser.add_argument("-c", "--iter-count", default=DEFAULT_ITER_COUNT, type=int, @@ -194,16 +202,23 @@ def save_measurements(path, measurements): f.write(str(measurement) + '\n') +def print_preface_text(test_name): + print("To analyze the results, use this script (we recommend using the median):" + + "\nhttps://github.com/mozilla-mobile/perf-tools/blob/master/analyze_durations.py") + if test_name == TEST_COLD_MAIN_FF: + print("\nWARNING: you may wish to clear the onboarding experience manually.") + elif test_name == TEST_COLD_VIEW_FF or test_name == TEST_COLD_VIEW_NAV_START: + print("\nWARNING: you may wish to reduce the number of open tabs when starting this test") + print("as this test may leave many additional tabs open which could impact the results.") + + def main(): args = parse_args() validate_args(args) - # Exceptions and script piping like these are why we prefer mozperftest. :) - print("Clear the onboarding experience manually, if it's desired and you haven't already done so.") - print("\nYou can use this script to find the average from the results file: https://github.com/mozilla-mobile/perf-tools/blob/master/analyze_durations.py") - pkg_id = CHANNEL_TO_PKG[args.release_channel] start_cmd = get_start_cmd(args.test_name, pkg_id) + print_preface_text(args.test_name) measurements = measure(args.test_name, pkg_id, start_cmd, args.iter_count) save_measurements(args.path, measurements) From b3ffdd2a472d3569ed96340c41606d0462c526c1 Mon Sep 17 00:00:00 2001 From: Michael Comella Date: Tue, 25 May 2021 19:18:49 -0700 Subject: [PATCH 006/500] For perf-frontend-issues#208: rename to measure_start_up.py. --- tools/{measure_time_to_first_frame.py => measure_start_up.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tools/{measure_time_to_first_frame.py => measure_start_up.py} (100%) diff --git a/tools/measure_time_to_first_frame.py b/tools/measure_start_up.py similarity index 100% rename from tools/measure_time_to_first_frame.py rename to tools/measure_start_up.py From 63eec5dfecdee407417acaa53303eda6522b1d99 Mon Sep 17 00:00:00 2001 From: Mozilla L10n Automation Bot Date: Wed, 2 Jun 2021 00:06:59 +0000 Subject: [PATCH 007/500] Import l10n. --- app/src/main/res/values-dsb/strings.xml | 3 ++ app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-fy-rNL/strings.xml | 3 ++ app/src/main/res/values-ia/strings.xml | 8 ++-- app/src/main/res/values-nl/strings.xml | 3 ++ app/src/main/res/values-th/strings.xml | 56 +++++++++++++--------- 6 files changed, 49 insertions(+), 26 deletions(-) diff --git a/app/src/main/res/values-dsb/strings.xml b/app/src/main/res/values-dsb/strings.xml index 917bda1c5ea6..af48fa46d767 100644 --- a/app/src/main/res/values-dsb/strings.xml +++ b/app/src/main/res/values-dsb/strings.xml @@ -1605,6 +1605,9 @@ Wótwóŕśo swój rěd + + Blokěrowanje wótpóraś, aby se skłaźone informacije kreditoweje kórty wužywali + Pytnicu pśidaś diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index bab7c8d40c1a..d4d2ad855bf3 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1624,6 +1624,8 @@ Cependant, il peut être moins stable. Téléchargez la version bêta de notre n Veuillez saisir un numéro de carte bancaire valide + + Déverrouillez pour afficher vos cartes enregistrées Protégez vos cartes bancaires diff --git a/app/src/main/res/values-fy-rNL/strings.xml b/app/src/main/res/values-fy-rNL/strings.xml index 0ded768cfb53..60283215d424 100644 --- a/app/src/main/res/values-fy-rNL/strings.xml +++ b/app/src/main/res/values-fy-rNL/strings.xml @@ -1605,6 +1605,9 @@ Untskoattelje jo apparaat + + Untskoattelje om bewarre creditkaartynformaasje te brûken + Sykmasine tafoegje diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index 41f56b1376df..d7367e6a22df 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -36,7 +36,7 @@ Exir del modo multiselection - Salvar schedas eligite al collection + Salvar le schedas seligite in un collection Selecte %1$s @@ -671,11 +671,11 @@ Clauder - Compartir schedas eligite + Compartir le schedas seligite - Menu del schedas eligite + Menu de schedas seligite Remover le scheda ex le collection @@ -979,7 +979,7 @@ - %d schedas eligite + %d schedas seligite %d scheda seligite diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 09adeb00fd1d..573177b63ccb 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -1613,6 +1613,9 @@ Ontgrendel uw apparaat + + Ontgrendelen om opgeslagen creditcardgegevens te gebruiken + Zoekmachine toevoegen diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 2ee95d0d1433..502856d4af0f 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -412,6 +412,11 @@ and the third is the device model. --> %1$s บน %2$s %3$s + + บัตรเครดิต + + ที่อยู่ + แท็บที่ได้รับ @@ -443,9 +448,6 @@ เรียนรู้เพิ่มเติม - - ปิดใช้งานสำหรับทุกไซต์แล้ว ให้ไปที่การตั้งค่าเพื่อเปิด - การวัดและส่งข้อมูลทางไกล @@ -456,6 +458,8 @@ ข้อมูลการตลาด แบ่งปันข้อมูลเกี่ยวกับคุณลักษณะที่คุณใช้ใน %1$s กับ Leanplum ผู้ให้บริการการตลาดมือถือของเรา + + แบ่งปันข้อมูลการใช้งานพื้นฐานกับ Adjust ผู้จำหน่ายการตลาดมือถือของเรา การศึกษา @@ -794,8 +798,6 @@ ลบ %1$s แล้ว เพิ่มโฟลเดอร์ - - สร้างที่คั่นหน้าแล้ว บันทึกที่คั่นหน้าแล้ว! @@ -1448,10 +1450,8 @@ การเติมอัตโนมัติ ซิงค์การเข้าสู่ระบบ - - เปิด - - ปิด + + ซิงค์การเข้าสู่ระบบระหว่างอุปกรณ์ เชื่อมต่อใหม่ @@ -1552,6 +1552,8 @@ ข้อมูลถูกเข้ารหัส ซิงค์บัตรระหว่างอุปกรณ์ + + ซิงค์บัตร เพิ่มบัตรเครดิต @@ -1583,6 +1585,23 @@ บัตรที่บันทึกไว้ + + โปรดป้อนหมายเลขบัตรเครดิตที่ถูกต้อง + + ปลดล็อกเพื่อดูบัตรเครดิตที่บันทึกไว้ของคุณ + + รักษาความปลอดภัยให้กับบัตรเครดิตของคุณ + + ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงบัตรเครดิตที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ + + ตั้งค่าตอนนี้ + + ภายหลัง + + ปลดล็อกอุปกรณ์ของคุณ + + ปลดล็อกเพื่อใช้ข้อมูลบัตรเครดิตที่เก็บไว้ + เพิ่มเครื่องมือค้นหา @@ -1748,20 +1767,13 @@ ลบ - - รับประโยชน์สูงสุดจาก %s - คลิกเพื่อดูรายละเอียดเพิ่มเติม - - รวบรวมสิ่งที่สำคัญสำหรับคุณ - - จัดกลุ่มการค้นหา ไซต์ และแท็บที่คล้ายกันเพื่อการเข้าถึงอย่างรวดเร็วในภายหลัง - - คุณลงชื่อเข้าในชื่อ %s บนเบราว์เซอร์ Firefox อื่นบนโทรศัพท์นี้ คุณต้องการลงชื่อเข้าด้วยบัญชีนี้หรือไม่? - - คุณสามารถเพิ่มเว็บไซต์นี้ลงในหน้าจอหลักของโทรศัพท์ของคุณเพื่อเข้าถึงและเรียกดูได้เร็วขึ้นด้วยประสบการณ์ที่เหมือนแอป + + นำทางขึ้นไปด้านบน + + + ปิด - + From f3e3f86388ee81c6c34df4f2c04b2a6586280c87 Mon Sep 17 00:00:00 2001 From: Oana Horvath Date: Fri, 28 May 2021 14:01:38 +0300 Subject: [PATCH 008/500] No issue: Change hardcoded package and app name in tests --- .../org/mozilla/fenix/AppRequestInterceptor.kt | 2 +- .../mozilla/fenix/helpers/HomeActivityTestRule.kt | 2 +- .../java/org/mozilla/fenix/helpers/TestHelper.kt | 5 ++++- .../org/mozilla/fenix/ui/SettingsBasicsTest.kt | 12 ------------ .../java/org/mozilla/fenix/ui/SmokeTest.kt | 4 ++-- .../org/mozilla/fenix/ui/robots/CustomTabRobot.kt | 6 +++--- .../org/mozilla/fenix/ui/robots/DownloadRobot.kt | 14 +++++++------- .../org/mozilla/fenix/ui/robots/HomeScreenRobot.kt | 10 +++++----- .../fenix/ui/robots/RecentlyClosedTabsRobot.kt | 3 ++- .../org/mozilla/fenix/ui/robots/SettingsRobot.kt | 5 +++-- .../fenix/ui/robots/SettingsSubMenuAboutRobot.kt | 9 +++++---- .../ui/robots/SettingsSubMenuAddonsManagerRobot.kt | 9 +++++---- .../robots/SettingsSubMenuDataCollectionRobot.kt | 3 ++- .../SettingsSubMenuDeleteBrowsingDataRobot.kt | 5 +++-- ...ttingsSubMenuEnhancedTrackingProtectionRobot.kt | 5 +++-- .../robots/SettingsSubMenuPrivateBrowsingRobot.kt | 7 ++++--- .../fenix/ui/robots/SettingsSubMenuSearchRobot.kt | 3 ++- .../org/mozilla/fenix/ui/robots/TabDrawerRobot.kt | 8 ++++---- .../fenix/ui/robots/ThreeDotMenuMainRobot.kt | 7 ++++--- 19 files changed, 60 insertions(+), 59 deletions(-) diff --git a/app/src/androidTest/java/org/mozilla/fenix/AppRequestInterceptor.kt b/app/src/androidTest/java/org/mozilla/fenix/AppRequestInterceptor.kt index 59e2de9a5c24..8fefecae2a9f 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/AppRequestInterceptor.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/AppRequestInterceptor.kt @@ -9,7 +9,7 @@ import androidx.navigation.NavController import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.request.RequestInterceptor import org.mozilla.fenix.ext.components -import org.mozilla.fenix.ui.robots.appContext +import org.mozilla.fenix.helpers.TestHelper.appContext import java.lang.ref.WeakReference /** diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt index 70247901fdbb..051dd9680db5 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt @@ -11,8 +11,8 @@ import androidx.test.rule.ActivityTestRule import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiSelector import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.helpers.TestHelper.appContext import org.mozilla.fenix.onboarding.FenixOnboarding -import org.mozilla.fenix.ui.robots.appContext /** * A [org.junit.Rule] to handle shared test set up for tests on [HomeActivity]. diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt index 30db0383c233..d12c90c64a11 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt @@ -30,6 +30,7 @@ import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import kotlinx.coroutines.runBlocking +import mozilla.components.support.ktx.android.content.appName import org.hamcrest.CoreMatchers import org.hamcrest.CoreMatchers.allOf import org.mozilla.fenix.R @@ -41,7 +42,9 @@ import java.io.File object TestHelper { - val packageName = InstrumentationRegistry.getInstrumentation().targetContext.packageName + val appContext: Context = InstrumentationRegistry.getInstrumentation().targetContext + val packageName: String = appContext.packageName + val appName = appContext.appName fun scrollToElementByText(text: String): UiScrollable { val appView = UiScrollable(UiSelector().scrollable(true)) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt index 39191b4ecc77..be1366a8553a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsBasicsTest.kt @@ -194,16 +194,4 @@ class SettingsBasicsTest { verifyMenuItemsAreDisabled() } } - - @Test - fun changeDefaultBrowserSetting() { - // Opens settings and toggles the default browser setting to on. The device settings open and allows the user to set a default browser. - homeScreen { - }.openThreeDotMenu { - }.openSettings { - verifyDefaultBrowserIsDisaled() - clickDefaultBrowserSwitch() - verifyAndroidDefaultAppsMenuAppears() - } - } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt index 1e5d40593cd2..f8209ba8c63b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -30,6 +30,7 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.RecyclerViewIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.TestHelper.createCustomTabIntent import org.mozilla.fenix.helpers.TestHelper.deleteDownloadFromStorage import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText @@ -1132,8 +1133,7 @@ class SmokeTest { verifyAddPrivateBrowsingShortcutButton() clickAddPrivateBrowsingShortcutButton() clickAddAutomaticallyButton() - }.openHomeScreenShortcut("Private Firefox Preview") { - } + }.openHomeScreenShortcut("Private $appName") {} } @Test diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt index 90f05e96a8bc..336255f3db38 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt @@ -11,9 +11,9 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.UiSelector import junit.framework.TestCase.assertTrue -import mozilla.components.support.ktx.android.content.appName import org.mozilla.fenix.R import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestHelper.appName /** * Implementation of the robot pattern for Custom tabs @@ -29,7 +29,7 @@ class CustomTabRobot { } fun verifyPoweredByTextIsDisplayed() { - mDevice.findObject(UiSelector().textContains("POWERED BY ${appContext.appName}")) + mDevice.findObject(UiSelector().textContains("POWERED BY $appName")) } fun verifyOpenInBrowserButtonExists() { @@ -75,7 +75,7 @@ private fun desktopSiteButton() = onView(withId(R.id.switch_widget)) private fun findInPageButton() = onView(withText("Find in page")) -private fun openInBrowserButton() = onView(withText("Open in ${appContext.appName}")) +private fun openInBrowserButton() = onView(withText("Open in $appName")) private fun refreshButton() = mDevice.findObject(UiSelector().description("Refresh")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt index aca0e0bf0998..00e1a091eec6 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt @@ -12,10 +12,10 @@ import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.matcher.RootMatchers.isDialog -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice @@ -24,13 +24,13 @@ import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers import org.junit.Assert.assertTrue import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.ext.waitNotNull -import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_APPS_PHOTOS -import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime -import org.mozilla.fenix.helpers.TestHelper.packageName /** * Implementation of Robot Pattern for download UI handling. @@ -52,13 +52,13 @@ class DownloadRobot { fun verifyDownloadedFileIcon() = assertDownloadedFileIcon() fun verifyEmptyDownloadsList() { - mDevice.findObject(UiSelector().resourceId("org.mozilla.fenix.debug:id/download_empty_view")) + mDevice.findObject(UiSelector().resourceId("$packageName:id/download_empty_view")) .waitForExists(waitingTime) onView(withText("No downloaded files")).check(matches(isDisplayed())) } fun waitForDownloadsListToExist() = - assertTrue(mDevice.findObject(UiSelector().resourceId("org.mozilla.fenix.debug:id/download_list")) + assertTrue(mDevice.findObject(UiSelector().resourceId("$packageName:id/download_list")) .waitForExists(waitingTime)) class Transition { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt index 2f62957d198a..3e1ca0801c43 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt @@ -38,7 +38,6 @@ import androidx.test.uiautomator.Until import androidx.test.uiautomator.Until.findObject import junit.framework.TestCase.assertTrue import mozilla.components.browser.state.state.searchEngines -import mozilla.components.support.ktx.android.content.appName import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.instanceOf @@ -48,6 +47,8 @@ import org.junit.Assert import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestHelper.appContext +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.click @@ -63,7 +64,7 @@ import org.mozilla.fenix.ui.util.STRING_ONBOARDING_TRACKING_PROTECTION_HEADER */ class HomeScreenRobot { val privateSessionMessage = - "${appContext.appName} clears your search and browsing history from private tabs when you close them" + + "$appName clears your search and browsing history from private tabs when you close them" + " or quit the app. While this doesn’t make you anonymous to websites or your internet" + " service provider, it makes it easier to keep what you do online private from anyone" + " else who uses this device." @@ -424,7 +425,6 @@ fun homeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition } val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) -val appContext = InstrumentationRegistry.getInstrumentation().targetContext private fun homeScreenList() = UiScrollable( @@ -510,7 +510,7 @@ private fun verifySearchEngineIcon(searchEngineName: String) { // First Run elements private fun assertWelcomeHeader() = - onView(allOf(withText("Welcome to ${appContext.appName}!"))) + onView(allOf(withText("Welcome to $appName!"))) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertStartSyncHeader() { @@ -597,7 +597,7 @@ private fun assertYourPrivacyText() { onView( allOf( withText( - "We’ve designed ${appContext.appName} to give you control over what you share online and what you share with us." + "We’ve designed $appName to give you control over what you share online and what you share with us." ) ) ) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt index c2bbd5cad53a..a817051cc6c3 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt @@ -18,6 +18,7 @@ import org.hamcrest.Matchers import org.hamcrest.Matchers.allOf import org.mozilla.fenix.R import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.helpers.click /** @@ -27,7 +28,7 @@ import org.mozilla.fenix.helpers.click class RecentlyClosedTabsRobot { fun waitForListToExist() = - mDevice.findObject(UiSelector().resourceId("org.mozilla.fenix.debug:id/recently_closed_list")) + mDevice.findObject(UiSelector().resourceId("$packageName:id/recently_closed_list")) .waitForExists( TestAssetHelper.waitingTime ) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt index c0d8f33bf809..7557c5096cf6 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt @@ -33,6 +33,7 @@ import org.hamcrest.CoreMatchers import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants.PackageName.GOOGLE_PLAY_SERVICES import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.assertIsEnabled import org.mozilla.fenix.helpers.click @@ -475,8 +476,8 @@ private fun assertRateOnGooglePlay(): ViewInteraction { private fun assertAboutFirefoxPreview(): ViewInteraction { onView(withId(R.id.recycler_view)) - .perform(RecyclerViewActions.scrollTo(hasDescendant(withText("About Firefox Preview")))) - return onView(withText("About Firefox Preview")) + .perform(RecyclerViewActions.scrollTo(hasDescendant(withText("About $appName")))) + return onView(withText("About $appName")) .check(matches(isDisplayed())) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt index fe6986fe4ee9..612311542fe7 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt @@ -28,6 +28,7 @@ import org.hamcrest.CoreMatchers.containsString import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.R import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.isVisibleForUser import org.mozilla.fenix.settings.SupportUtils import java.text.SimpleDateFormat @@ -108,7 +109,7 @@ private fun assertVersionNumber() { private fun assertProductCompany() { onView(withId(R.id.about_content)) - .check(matches(withText(containsString("Firefox Preview is produced by Mozilla.")))) + .check(matches(withText(containsString("$appName is produced by Mozilla.")))) } private fun assertCurrentTimestamp() { @@ -122,11 +123,11 @@ private fun assertCurrentTimestamp() { private fun assertWhatIsNewInFirefoxPreview() { - if (!onView(withText("What’s new in Firefox Preview")).isVisibleForUser()) { + if (!onView(withText("What’s new in $appName")).isVisibleForUser()) { onView(withId(R.id.about_layout)).perform(ViewActions.swipeUp()) } - onView(withText("What’s new in Firefox Preview")) + onView(withText("What’s new in $appName")) .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) .perform(click()) @@ -222,7 +223,7 @@ private fun assertLibrariesUsed() { .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) .perform(click()) - onView(withId(R.id.navigationToolbar)).check(matches(hasDescendant(withText(containsString("Firefox Preview | OSS Libraries"))))) + onView(withId(R.id.navigationToolbar)).check(matches(hasDescendant(withText(containsString("$appName | OSS Libraries"))))) Espresso.pressBack() } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt index 102367770f66..c370b3c8a84d 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt @@ -4,17 +4,17 @@ import android.widget.RelativeLayout import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.hasSibling import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA import androidx.test.espresso.matcher.ViewMatchers.withContentDescription -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility -import androidx.test.espresso.matcher.ViewMatchers.Visibility +import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withParent +import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers.allOf @@ -27,6 +27,7 @@ import org.mozilla.fenix.helpers.IdlingResourceHelper.registerAddonInstallingIdl import org.mozilla.fenix.helpers.IdlingResourceHelper.unregisterAddonInstallingIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.ext.waitNotNull @@ -132,7 +133,7 @@ class SettingsSubMenuAddonsManagerRobot { allOf( withText("Okay, Got it"), withParent(instanceOf(RelativeLayout::class.java)), - hasSibling(withText("$addonName has been added to Firefox Preview")), + hasSibling(withText("$addonName has been added to $appName")), hasSibling(withText("Open it in the menu")), hasSibling(withText("Allow in private browsing")) ) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDataCollectionRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDataCollectionRobot.kt index c4dbca48074c..3b638d688798 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDataCollectionRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDataCollectionRobot.kt @@ -16,6 +16,7 @@ import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import org.hamcrest.CoreMatchers.allOf import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.assertIsEnabled import org.mozilla.fenix.helpers.click @@ -68,7 +69,7 @@ private fun assertDataCollectionOptions() { .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) val usageAndTechnicalDataText = - "Shares performance, usage, hardware and customization data about your browser with Mozilla to help us make Firefox Preview better" + "Shares performance, usage, hardware and customization data about your browser with Mozilla to help us make $appName better" onView(withText(usageAndTechnicalDataText)) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDeleteBrowsingDataRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDeleteBrowsingDataRobot.kt index 32ab7c4f2f0d..dcea2d465fe4 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDeleteBrowsingDataRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuDeleteBrowsingDataRobot.kt @@ -21,9 +21,10 @@ import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers.allOf import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.assertIsChecked import org.mozilla.fenix.helpers.click -import org.mozilla.fenix.helpers.TestAssetHelper /** * Implementation of Robot Pattern for the settings Delete Browsing Data sub menu. @@ -104,7 +105,7 @@ private fun cancelButton() = mDevice.findObject(UiSelector().textStartsWith("CANCEL")) private fun assertMessageInDialogBox() = - onView(withText("Firefox Preview will delete the selected browsing data.")) + onView(withText("$appName will delete the selected browsing data.")) .inRoot(isDialog()) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuEnhancedTrackingProtectionRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuEnhancedTrackingProtectionRobot.kt index e3fe7d6fad28..3a30b2e2576b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuEnhancedTrackingProtectionRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuEnhancedTrackingProtectionRobot.kt @@ -10,9 +10,9 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.hasSibling -import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withChild import androidx.test.espresso.matcher.ViewMatchers.withContentDescription @@ -26,6 +26,7 @@ import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.not +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.assertIsChecked import org.mozilla.fenix.helpers.click @@ -122,7 +123,7 @@ private fun assertEnhancedTrackingProtectionHeader() { private fun assertEnhancedTrackingProtectionHeaderDescription() { onView(allOf(withParent(withParentIndex(0)), - withText("Keep your data to yourself. Firefox Preview protects you from many of the most common trackers that follow what you do online."))) + withText("Keep your data to yourself. $appName protects you from many of the most common trackers that follow what you do online."))) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuPrivateBrowsingRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuPrivateBrowsingRobot.kt index c8ef29dd0951..4a5a23438b76 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuPrivateBrowsingRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuPrivateBrowsingRobot.kt @@ -25,6 +25,7 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.mozilla.fenix.R import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestHelper.appName import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.isEnabled @@ -104,7 +105,7 @@ private fun goBackButton() = onView(withContentDescription("Navigate up")) private fun addAutomaticallyButton() = mDevice.findObject(UiSelector().textStartsWith("add automatically")) -private fun privateBrowsingShortcutIcon() = mDevice.findObject(text("Private Firefox Preview")) +private fun privateBrowsingShortcutIcon() = mDevice.findObject(text("Private $appName")) private fun assertAddPrivateBrowsingShortcutButton() { mDevice.wait( @@ -130,6 +131,6 @@ private fun assertOpenLinksInPrivateTabOff() { } private fun assertPrivateBrowsingShortcutIcon() { - mDevice.wait(Until.findObject(text("Private Firefox Preview")), waitingTime) - assertTrue(mDevice.hasObject(text("Private Firefox Preview"))) + mDevice.wait(Until.findObject(text("Private $appName")), waitingTime) + assertTrue(mDevice.hasObject(text("Private $appName"))) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt index 92c29ce008e9..435ce4a8f518 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSearchRobot.kt @@ -24,6 +24,7 @@ import androidx.test.uiautomator.UiSelector import org.hamcrest.CoreMatchers import org.mozilla.fenix.R import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.helpers.click /** @@ -53,7 +54,7 @@ class SettingsSubMenuSearchRobot { fun saveNewSearchEngine() { addSearchEngineSaveButton().click() mDevice.findObject( - UiSelector().resourceId("org.mozilla.fenix.debug:id/recycler_view") + UiSelector().resourceId("$packageName:id/recycler_view") ).waitForExists(waitingTime) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt index 8a9256817d36..18327df438ec 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt @@ -60,7 +60,7 @@ class TabDrawerRobot { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) mDevice.waitNotNull( - Until.findObject(By.res("org.mozilla.fenix.debug:id/mozac_browser_tabstray_url")), + Until.findObject(By.res("$packageName:id/mozac_browser_tabstray_url")), waitingTime ) onView(withId(R.id.mozac_browser_tabstray_url)) @@ -88,7 +88,7 @@ class TabDrawerRobot { fun closeTab() { mDevice.findObject( - UiSelector().resourceId("org.mozilla.fenix.debug:id/mozac_browser_tabstray_close") + UiSelector().resourceId("$packageName:id/mozac_browser_tabstray_close") ).waitForExists(waitingTime) var retries = 0 // number of retries before failing, will stop at 2 @@ -96,7 +96,7 @@ class TabDrawerRobot { closeTabButton().click() retries++ } while (mDevice.findObject( - UiSelector().resourceId("org.mozilla.fenix.debug:id/mozac_browser_tabstray_close") + UiSelector().resourceId("$packageName:id/mozac_browser_tabstray_close") ).exists() && retries < 3 ) } @@ -150,7 +150,7 @@ class TabDrawerRobot { mDevice.waitNotNull( findObject( By - .res("org.mozilla.fenix.debug:id/play_pause_button") + .res("$packageName:id/play_pause_button") .desc(action) ), waitingTime diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt index 9db6eef94ae9..422e594d645c 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt @@ -33,6 +33,7 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.mozilla.fenix.R import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.ext.waitNotNull import org.mozilla.fenix.share.ShareFragment @@ -179,7 +180,7 @@ class ThreeDotMenuMainRobot { mDevice.waitNotNull(Until.findObject(By.text("Bookmarks")), waitingTime) bookmarksButton().click() - assertTrue(mDevice.findObject(UiSelector().resourceId("org.mozilla.fenix.debug:id/bookmark_list")).waitForExists(waitingTime)) + assertTrue(mDevice.findObject(UiSelector().resourceId("$packageName:id/bookmark_list")).waitForExists(waitingTime)) BookmarksRobot().interact() return BookmarksRobot.Transition() @@ -301,7 +302,7 @@ class ThreeDotMenuMainRobot { interact: BrowserRobot.() -> Unit ): BrowserRobot.Transition { mDevice.wait( - Until.findObject(By.res("org.mozilla.fenix.debug:id/name_collection_edittext")), + Until.findObject(By.res("$packageName:id/name_collection_edittext")), waitingTime ) @@ -310,7 +311,7 @@ class ThreeDotMenuMainRobot { ViewActions.pressImeActionButton() ) // wait for the collection creation wrapper to be dismissed - mDevice.waitNotNull(Until.gone(By.res("org.mozilla.fenix.debug:id/createCollectionWrapper"))) + mDevice.waitNotNull(Until.gone(By.res("$packageName:id/createCollectionWrapper"))) BrowserRobot().interact() return BrowserRobot.Transition() From e48d285114c866076e26c031d279cd413df19716 Mon Sep 17 00:00:00 2001 From: Oana Horvath Date: Fri, 28 May 2021 15:47:21 +0300 Subject: [PATCH 009/500] No issue: Add more smoke tests coverage --- .../java/org/mozilla/fenix/ui/SmokeTest.kt | 23 +++++++++++++++++-- .../mozilla/fenix/ui/robots/SettingsRobot.kt | 10 ++------ .../SettingsSubMenuAddonsManagerRobot.kt | 7 +++--- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt index f8209ba8c63b..1a8de408104b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -26,7 +26,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.helpers.AndroidAssetDispatcher -import org.mozilla.fenix.helpers.HomeActivityTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.RecyclerViewIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper @@ -45,6 +45,7 @@ import org.mozilla.fenix.ui.robots.enhancedTrackingProtection import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar import org.mozilla.fenix.ui.robots.notificationShade +import org.mozilla.fenix.ui.robots.searchScreen import org.mozilla.fenix.ui.robots.tabDrawer import org.mozilla.fenix.ui.util.STRING_ONBOARDING_TRACKING_PROTECTION_HEADER @@ -76,7 +77,7 @@ class SmokeTest { } @get:Rule - val activityTestRule = HomeActivityTestRule() + val activityTestRule = HomeActivityIntentTestRule() private lateinit var browserStore: BrowserStore @get: Rule @@ -1134,6 +1135,11 @@ class SmokeTest { clickAddPrivateBrowsingShortcutButton() clickAddAutomaticallyButton() }.openHomeScreenShortcut("Private $appName") {} + searchScreen { + verifySearchView() + }.dismissSearchBar { + verifyPrivateSessionMessage() + } } @Test @@ -1320,4 +1326,17 @@ class SmokeTest { assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED) } } + + @Test + // For API>23 + // Verifies the default browser switch opens the system default apps menu. + fun changeDefaultBrowserSetting() { + homeScreen { + }.openThreeDotMenu { + }.openSettings { + verifyDefaultBrowserIsDisaled() + clickDefaultBrowserSwitch() + verifyAndroidDefaultAppsMenuAppears() + } + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt index 7557c5096cf6..fc02dd5baa2e 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt @@ -311,14 +311,8 @@ private fun assertDefaultBrowserIsDisabled() { } private fun toggleDefaultBrowserSwitch() { - scrollToElementByText("Set as default browser") - onView( - CoreMatchers.allOf( - ViewMatchers.withParent(CoreMatchers.not(withId(R.id.navigationToolbar))), - withText("Set as default browser") - ) - ) - .perform(ViewActions.click()) + scrollToElementByText("Privacy and security") + onView(withText("Set as default browser")).perform(ViewActions.click()) } private fun assertAndroidDefaultAppsMenuAppears() { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt index c370b3c8a84d..8c048afea1e4 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt @@ -15,14 +15,15 @@ import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withParent import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.rule.ActivityTestRule import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.instanceOf import org.hamcrest.CoreMatchers.not +import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R -import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.IdlingResourceHelper.registerAddonInstallingIdlingResource import org.mozilla.fenix.helpers.IdlingResourceHelper.unregisterAddonInstallingIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime @@ -38,7 +39,7 @@ import org.mozilla.fenix.helpers.ext.waitNotNull class SettingsSubMenuAddonsManagerRobot { fun verifyAddonPrompt(addonName: String) = assertAddonPrompt(addonName) fun clickInstallAddon(addonName: String) = selectInstallAddon(addonName) - fun verifyDownloadAddonPrompt(addonName: String, activityTestRule: HomeActivityTestRule) = + fun verifyDownloadAddonPrompt(addonName: String, activityTestRule: ActivityTestRule) = assertDownloadingAddonPrompt(addonName, activityTestRule) fun cancelInstallAddon() = cancelInstall() @@ -125,7 +126,7 @@ class SettingsSubMenuAddonsManagerRobot { private fun assertDownloadingAddonPrompt( addonName: String, - activityTestRule: HomeActivityTestRule + activityTestRule: ActivityTestRule ) { registerAddonInstallingIdlingResource(activityTestRule) From 5ab3ee60d7912dbf5568f2589deaedc6938c6757 Mon Sep 17 00:00:00 2001 From: MickeyMoz Date: Wed, 2 Jun 2021 13:22:56 +0000 Subject: [PATCH 010/500] Update Android Components version to 91.0.20210601143118. --- buildSrc/src/main/java/AndroidComponents.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/java/AndroidComponents.kt b/buildSrc/src/main/java/AndroidComponents.kt index 115d839e501b..dac45351844d 100644 --- a/buildSrc/src/main/java/AndroidComponents.kt +++ b/buildSrc/src/main/java/AndroidComponents.kt @@ -3,5 +3,5 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ object AndroidComponents { - const val VERSION = "90.0.20210531190346" + const val VERSION = "91.0.20210601143118" } From 318aace1eb0060c60d76f708082879f202b774b0 Mon Sep 17 00:00:00 2001 From: Mihai Adrian Carare <48995920+mcarare@users.noreply.github.com> Date: Wed, 2 Jun 2021 17:56:30 +0300 Subject: [PATCH 011/500] For #19419 - Label edit boxes for a11y services. (#19762) --- app/src/main/res/layout/fragment_credit_card_editor.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/layout/fragment_credit_card_editor.xml b/app/src/main/res/layout/fragment_credit_card_editor.xml index 85a04639d4b8..f31d865a07ae 100644 --- a/app/src/main/res/layout/fragment_credit_card_editor.xml +++ b/app/src/main/res/layout/fragment_credit_card_editor.xml @@ -26,6 +26,7 @@ android:text="@string/credit_cards_card_number" android:textColor="?primaryText" android:textSize="12sp" + android:labelFor="@id/card_number_input" app:fontFamily="@font/metropolis_semibold" /> Date: Mon, 31 May 2021 16:37:46 +0300 Subject: [PATCH 012/500] For #19571 - Adds gdprForgetMe when stopping Adjust --- .../org/mozilla/fenix/components/metrics/AdjustMetricsService.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt index baf4566d8b30..18c0906e0380 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/AdjustMetricsService.kt @@ -67,6 +67,7 @@ class AdjustMetricsService(private val application: Application) : MetricsServic override fun stop() { Adjust.setEnabled(false) + Adjust.gdprForgetMe(application.applicationContext) } // We're not currently sending events directly to Adjust From eaf74a18685881601fd1f9393e1182ec92cd7f35 Mon Sep 17 00:00:00 2001 From: Stefan Arentz Date: Wed, 2 Jun 2021 12:49:02 -0400 Subject: [PATCH 013/500] Fixes #19773 - Add a needs:review label to the automatic String Sync PRs (#19774) --- .github/workflows/sync-strings.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/sync-strings.yml b/.github/workflows/sync-strings.yml index 6578c36a137d..932f4a1d5683 100644 --- a/.github/workflows/sync-strings.yml +++ b/.github/workflows/sync-strings.yml @@ -39,3 +39,4 @@ jobs: branch: automation/sync-strings-${{ steps.fenix-beta-version.outputs.major-beta-version }} title: "Sync Strings from master to releases_${{steps.fenix-beta-version.outputs.fenix-beta-version}}.0" body: "This (automated) PR syncs strings from `master` to `releases_${{steps.fenix-beta-version.outputs.fenix-beta-version}}.0.0`" + labels: needs:review From 6dbe5acc5b25b16677370eca57131a632a60173c Mon Sep 17 00:00:00 2001 From: Elise Richards Date: Wed, 2 Jun 2021 14:19:00 -0500 Subject: [PATCH 014/500] For #19746 - Remove feature flag for the three-dot menu redesign (#19750) * Remove feature flag for the three-dot menu redesign * Remove menu feature flag from unit tests --- .../java/org/mozilla/fenix/FeatureFlags.kt | 5 - .../components/toolbar/DefaultToolbarMenu.kt | 199 +----------------- .../java/org/mozilla/fenix/home/HomeMenu.kt | 116 +--------- ...DefaultBrowserToolbarMenuControllerTest.kt | 97 ++++----- .../fenix/toolbar/DefaultToolbarMenuTest.kt | 65 +++--- 5 files changed, 77 insertions(+), 405 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index 2d91f73e03e6..e61457462a80 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -34,11 +34,6 @@ object FeatureFlags { */ val webAuthFeature = Config.channel.isNightlyOrDebug - /** - * Shows new three-dot toolbar menu design. - */ - const val toolbarMenuFeature = true - /** * Enables the tabs tray re-write with Synced Tabs. */ diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index 0cf53913a5b2..c8a07bdf0cf3 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -34,15 +34,11 @@ import mozilla.components.feature.webcompat.reporter.WebCompatReporterFeature import mozilla.components.lib.state.ext.flowScoped import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite -import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R -import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.accounts.FenixAccountManager import org.mozilla.fenix.experiments.ExperimentBranch import org.mozilla.fenix.experiments.FeatureId -import org.mozilla.fenix.ext.asActivity import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.withExperiment @@ -82,12 +78,7 @@ open class DefaultToolbarMenu( override val menuBuilder by lazy { WebExtensionBrowserMenuBuilder( - items = - if (FeatureFlags.toolbarMenuFeature) { - newCoreMenuItems - } else { - oldCoreMenuItems - }, + items = coreMenuItems, endOfMenuAlwaysVisible = shouldUseBottomToolbar, store = store, style = WebExtensionBrowserMenuBuilder.Style( @@ -161,27 +152,7 @@ open class DefaultToolbarMenu( registerForIsBookmarkedUpdates() - if (FeatureFlags.toolbarMenuFeature) { - BrowserMenuItemToolbar(listOf(back, forward, share, refresh), isSticky = true) - } else { - val bookmark = BrowserMenuItemToolbar.TwoStateButton( - primaryImageResource = R.drawable.ic_bookmark_filled, - primaryContentDescription = context.getString(R.string.browser_menu_edit_bookmark), - primaryImageTintResource = primaryTextColor(), - // TwoStateButton.isInPrimaryState must be synchronous, and checking bookmark state is - // relatively slow. The best we can do here is periodically compute and cache a new "is - // bookmarked" state, and use that whenever the menu has been opened. - isInPrimaryState = { isCurrentUrlBookmarked }, - secondaryImageResource = R.drawable.ic_bookmark_outline, - secondaryContentDescription = context.getString(R.string.browser_menu_bookmark), - secondaryImageTintResource = primaryTextColor(), - disableInSecondaryState = false - ) { - handleBookmarkItemTapped() - } - - BrowserMenuItemToolbar(listOf(back, forward, bookmark, share, refresh)) - } + BrowserMenuItemToolbar(listOf(back, forward, share, refresh), isSticky = true) } // Predicates that need to be repeatedly called as the session changes @@ -222,170 +193,6 @@ open class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.InstallPwaToHomeScreen) } - private val oldCoreMenuItems by lazy { - val settings = BrowserMenuHighlightableItem( - label = context.getString(R.string.browser_menu_settings), - startImageResource = R.drawable.ic_settings, - iconTintColorResource = if (hasAccountProblem) - ThemeManager.resolveAttribute(R.attr.syncDisconnected, context) else - primaryTextColor(), - textColorResource = if (hasAccountProblem) - ThemeManager.resolveAttribute(R.attr.primaryText, context) else - primaryTextColor(), - highlight = BrowserMenuHighlight.HighPriority( - endImageResource = R.drawable.ic_sync_disconnected, - backgroundTint = context.getColorFromAttr(R.attr.syncDisconnectedBackground), - canPropagate = false - ), - isHighlighted = { hasAccountProblem } - ) { - onItemTapped.invoke(ToolbarMenu.Item.Settings) - } - - val desktopMode = BrowserMenuImageSwitch( - imageResource = R.drawable.ic_desktop, - label = context.getString(R.string.browser_menu_desktop_site), - initialState = { - selectedSession?.content?.desktopMode ?: false - } - ) { checked -> - onItemTapped.invoke(ToolbarMenu.Item.RequestDesktop(checked)) - } - - val addToTopSites = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_add_to_top_sites), - imageResource = R.drawable.ic_top_sites, - iconTintColorResource = primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.AddToTopSites) - } - - val addToHomescreen = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_add_to_homescreen), - imageResource = R.drawable.ic_add_to_homescreen, - iconTintColorResource = primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.AddToHomeScreen) - } - - val syncedTabs = BrowserMenuImageText( - label = context.getString(R.string.synced_tabs), - imageResource = R.drawable.ic_synced_tabs, - iconTintColorResource = primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.SyncedTabs) - } - - val findInPage = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_find_in_page), - imageResource = R.drawable.mozac_ic_search, - iconTintColorResource = primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.FindInPage) - } - - val reportSiteIssuePlaceholder = WebExtensionPlaceholderMenuItem( - id = WebCompatReporterFeature.WEBCOMPAT_REPORTER_EXTENSION_ID - ) - - val saveToCollection = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_save_to_collection_2), - imageResource = R.drawable.ic_tab_collection, - iconTintColorResource = primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.SaveToCollection) - } - - val deleteDataOnQuit = BrowserMenuImageText( - label = context.getString(R.string.delete_browsing_data_on_quit_action), - imageResource = R.drawable.ic_exit, - iconTintColorResource = primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.Quit) - } - - val readerAppearance = BrowserMenuImageText( - label = context.getString(R.string.browser_menu_read_appearance), - imageResource = R.drawable.ic_readermode_appearance, - iconTintColorResource = primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.CustomizeReaderView) - } - - val openInApp = BrowserMenuHighlightableItem( - label = context.getString(R.string.browser_menu_open_app_link), - startImageResource = R.drawable.ic_open_in_app, - iconTintColorResource = primaryTextColor(), - highlight = BrowserMenuHighlight.LowPriority( - label = context.getString(R.string.browser_menu_open_app_link), - notificationTint = getColor(context, R.color.whats_new_notification_color) - ), - isHighlighted = { !context.settings().openInAppOpened } - ) { - onItemTapped.invoke(ToolbarMenu.Item.OpenInApp) - } - - val historyItem = BrowserMenuImageText( - context.getString(R.string.library_history), - R.drawable.ic_history, - primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.History) - } - - val bookmarksItem = BrowserMenuImageText( - context.getString(R.string.library_bookmarks), - R.drawable.ic_bookmark_filled, - primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.Bookmarks) - } - - val downloadsItem = BrowserMenuImageText( - context.getString(R.string.library_downloads), - R.drawable.ic_download, - primaryTextColor() - ) { - onItemTapped.invoke(ToolbarMenu.Item.Downloads) - } - - // Predicates that are called once, during screen init - val shouldShowSaveToCollection = (context.asActivity() as? HomeActivity) - ?.browsingModeManager?.mode == BrowsingMode.Normal - val shouldDeleteDataOnQuit = context.components.settings - .shouldDeleteBrowsingDataOnQuit - - val menuItems = listOfNotNull( - downloadsItem, - historyItem, - bookmarksItem, - syncedTabs, - settings, - if (shouldDeleteDataOnQuit) deleteDataOnQuit else null, - BrowserMenuDivider(), - reportSiteIssuePlaceholder, - findInPage, - getSetDefaultBrowserItem()?.let { BrowserMenuDivider() }, - getSetDefaultBrowserItem(), - getSetDefaultBrowserItem()?.let { BrowserMenuDivider() }, - addToTopSites, - addToHomescreen.apply { visible = ::canAddToHomescreen }, - installToHomescreen.apply { visible = ::canInstall }, - if (shouldShowSaveToCollection) saveToCollection else null, - desktopMode, - openInApp.apply { visible = ::shouldShowOpenInApp }, - readerAppearance.apply { visible = ::shouldShowReaderViewCustomization }, - BrowserMenuDivider(), - menuToolbar - ) - - if (shouldUseBottomToolbar) { - menuItems - } else { - menuItems.reversed() - } - } - val newTabItem = BrowserMenuImageText( context.getString(R.string.library_new_tab), R.drawable.ic_new, @@ -554,7 +361,7 @@ open class DefaultToolbarMenu( } @VisibleForTesting(otherwise = PRIVATE) - val newCoreMenuItems by lazy { + val coreMenuItems by lazy { val menuItems = listOfNotNull( if (shouldUseBottomToolbar) null else menuToolbar, diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt index 4184f59db36b..ca8334aee43c 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt @@ -23,7 +23,6 @@ import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import mozilla.components.support.ktx.android.content.getColorFromAttr -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite import org.mozilla.fenix.R import org.mozilla.fenix.components.accounts.FenixAccountManager @@ -120,104 +119,6 @@ class HomeMenu( onItemTapped.invoke(Item.SyncAccount(accountManager.signedInToFxa())) } - private val oldCoreMenuItems by lazy { - val whatsNewItem = BrowserMenuHighlightableItem( - context.getString(R.string.browser_menu_whats_new), - R.drawable.ic_whats_new, - iconTintColorResource = primaryTextColor, - highlight = BrowserMenuHighlight.LowPriority( - notificationTint = getColor(context, R.color.whats_new_notification_color) - ), - isHighlighted = { WhatsNew.shouldHighlightWhatsNew(context) } - ) { - onItemTapped.invoke(Item.WhatsNew) - } - val experiments = context.components.analytics.experiments - val bookmarksItem = BrowserMenuImageText( - context.getString(R.string.library_bookmarks), - R.drawable.ic_bookmark_list, - primaryTextColor - ) { - onItemTapped.invoke(Item.Bookmarks) - } - - val historyItem = BrowserMenuImageText( - context.getString(R.string.library_history), - R.drawable.ic_history, - primaryTextColor - ) { - onItemTapped.invoke(Item.History) - } - - val addons = BrowserMenuImageText( - context.getString(R.string.browser_menu_add_ons), - R.drawable.ic_addons_extensions, - primaryTextColor - ) { - onItemTapped.invoke(Item.Extensions) - } - - // Use nimbus to set the icon and title. - val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION) - val settingsItem = BrowserMenuImageText( - variables.getText("settings-title") ?: context.getString(R.string.browser_menu_settings), - variables.getDrawableResource("settings-icon") ?: R.drawable.ic_settings, - primaryTextColor - ) { - onItemTapped.invoke(Item.Settings) - } - - val helpItem = BrowserMenuImageText( - context.getString(R.string.browser_menu_help), - R.drawable.ic_help, - primaryTextColor - ) { - onItemTapped.invoke(Item.Help) - } - - val downloadsItem = BrowserMenuImageText( - context.getString(R.string.library_downloads), - R.drawable.ic_download, - primaryTextColor - ) { - onItemTapped.invoke(Item.Downloads) - } - - // Only query account manager if it has been initialized. - // We don't want to cause its initialization just for this check. - val accountAuthItem = if (context.components.backgroundServices.accountManagerAvailableQueue.isReady()) { - if (context.components.backgroundServices.accountManager.accountNeedsReauth()) reconnectToSyncItem else null - } else { - null - } - - val settings = context.components.settings - - val menuItems = listOfNotNull( - if (settings.shouldDeleteBrowsingDataOnQuit) quitItem else null, - settingsItem, - BrowserMenuDivider(), - syncedTabsItem, - bookmarksItem, - historyItem, - downloadsItem, - BrowserMenuDivider(), - addons, - BrowserMenuDivider(), - whatsNewItem, - helpItem, - accountAuthItem - ).also { items -> - items.getHighlight()?.let { onHighlightPresent(it) } - } - - if (shouldUseBottomToolbar) { - menuItems.reversed() - } else { - menuItems - } - } - val desktopItem = BrowserMenuImageSwitch( imageResource = R.drawable.ic_desktop, label = context.getString(R.string.browser_menu_desktop_site), @@ -227,7 +128,7 @@ class HomeMenu( } @Suppress("ComplexMethod") - private fun newCoreMenuItems(): List { + private fun coreMenuItems(): List { val experiments = context.components.analytics.experiments val settings = context.components.settings @@ -325,22 +226,11 @@ class HomeMenu( } init { - val menuItems = if (FeatureFlags.toolbarMenuFeature) { - newCoreMenuItems() - } else { - oldCoreMenuItems - } + val menuItems = coreMenuItems() // Report initial state. onMenuBuilderChanged(BrowserMenuBuilder(menuItems)) - val menuItemsWithReconnectItem = if (FeatureFlags.toolbarMenuFeature) { - menuItems - } else { - // reconnect item is manually added to the beginning of the list - listOf(reconnectToSyncItem) + menuItems - } - // Observe account state changes, and update menu item builder with a new set of items. context.components.backgroundServices.accountManagerAvailableQueue.runIfReadyOrQueue { // This task isn't relevant if our parent fragment isn't around anymore. @@ -352,7 +242,7 @@ class HomeMenu( lifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { onMenuBuilderChanged( BrowserMenuBuilder( - menuItemsWithReconnectItem + menuItems ) ) } diff --git a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt index a6097743131a..bf6bd08e2b53 100644 --- a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt @@ -48,7 +48,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.NavGraphDirections import org.mozilla.fenix.R @@ -68,7 +67,6 @@ import org.mozilla.fenix.utils.Settings @OptIn(ExperimentalCoroutinesApi::class) @RunWith(FenixRobolectricTestRunner::class) -@Suppress("ForbiddenComment") class DefaultBrowserToolbarMenuControllerTest { @get:Rule @@ -137,76 +135,67 @@ class DefaultBrowserToolbarMenuControllerTest { unmockkObject(FenixSnackbar.Companion) } - // TODO: These can be removed for https://github.com/mozilla-mobile/fenix/issues/17870 - // todo === Start === @Test fun handleToolbarBookmarkPressWithReaderModeInactive() = runBlockingTest { - if (!FeatureFlags.toolbarMenuFeature) { - val item = ToolbarMenu.Item.Bookmark - - val title = "Mozilla" - val url = "https://mozilla.org" - val regularTab = createTab( - url = url, - readerState = ReaderState(active = false, activeUrl = "https://1234.org"), - title = title - ) - val store = - BrowserStore(BrowserState(tabs = listOf(regularTab), selectedTabId = regularTab.id)) + val item = ToolbarMenu.Item.Bookmark - val controller = createController(scope = this, store = store) - controller.handleToolbarItemInteraction(item) + val title = "Mozilla" + val url = "https://mozilla.org" + val regularTab = createTab( + url = url, + readerState = ReaderState(active = false, activeUrl = "https://1234.org"), + title = title + ) + val store = + BrowserStore(BrowserState(tabs = listOf(regularTab), selectedTabId = regularTab.id)) - verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BOOKMARK)) } - verify { bookmarkTapped(url, title) } - } + val controller = createController(scope = this, store = store) + controller.handleToolbarItemInteraction(item) + + verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BOOKMARK)) } + verify { bookmarkTapped(url, title) } } @Test fun `IF reader mode is active WHEN bookmark menu item is pressed THEN menu item is handled`() = runBlockingTest { - if (!FeatureFlags.toolbarMenuFeature) { - val item = ToolbarMenu.Item.Bookmark - val title = "Mozilla" - val readerUrl = "moz-extension://1234" - val readerTab = createTab( - url = readerUrl, - readerState = ReaderState(active = true, activeUrl = "https://mozilla.org"), - title = title - ) - browserStore = - BrowserStore(BrowserState(tabs = listOf(readerTab), selectedTabId = readerTab.id)) + val item = ToolbarMenu.Item.Bookmark + val title = "Mozilla" + val readerUrl = "moz-extension://1234" + val readerTab = createTab( + url = readerUrl, + readerState = ReaderState(active = true, activeUrl = "https://mozilla.org"), + title = title + ) + browserStore = + BrowserStore(BrowserState(tabs = listOf(readerTab), selectedTabId = readerTab.id)) - val controller = createController(scope = this, store = browserStore) - controller.handleToolbarItemInteraction(item) + val controller = createController(scope = this, store = browserStore) + controller.handleToolbarItemInteraction(item) - verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BOOKMARK)) } - verify { bookmarkTapped("https://mozilla.org", title) } - } + verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BOOKMARK)) } + verify { bookmarkTapped("https://mozilla.org", title) } } @Test fun `WHEN open in Fenix menu item is pressed THEN menu item is handled correctly`() = runBlockingTest { - if (!FeatureFlags.toolbarMenuFeature) { - val customTab = createCustomTab("https://mozilla.org") - browserStore.dispatch(CustomTabListAction.AddCustomTabAction(customTab)).joinBlocking() - val controller = createController( - scope = this, - store = browserStore, - customTabSessionId = customTab.id - ) + val customTab = createCustomTab("https://mozilla.org") + browserStore.dispatch(CustomTabListAction.AddCustomTabAction(customTab)).joinBlocking() + val controller = createController( + scope = this, + store = browserStore, + customTabSessionId = customTab.id + ) - val item = ToolbarMenu.Item.OpenInFenix + val item = ToolbarMenu.Item.OpenInFenix - every { activity.startActivity(any()) } just Runs - controller.handleToolbarItemInteraction(item) + every { activity.startActivity(any()) } just Runs + controller.handleToolbarItemInteraction(item) - verify { sessionFeature.release() } - verify { customTabUseCases.migrate(customTab.id, true) } - verify { activity.startActivity(openInFenixIntent) } - verify { activity.finishAndRemoveTask() } - } + verify { sessionFeature.release() } + verify { customTabUseCases.migrate(customTab.id, true) } + verify { activity.startActivity(openInFenixIntent) } + verify { activity.finishAndRemoveTask() } } - // todo === End === @Test fun `WHEN reader mode menu item is pressed THEN handle appearance change`() = runBlockingTest { diff --git a/app/src/test/java/org/mozilla/fenix/toolbar/DefaultToolbarMenuTest.kt b/app/src/test/java/org/mozilla/fenix/toolbar/DefaultToolbarMenuTest.kt index 98f79432d65c..f199f6dbaeb5 100644 --- a/app/src/test/java/org/mozilla/fenix/toolbar/DefaultToolbarMenuTest.kt +++ b/app/src/test/java/org/mozilla/fenix/toolbar/DefaultToolbarMenuTest.kt @@ -26,7 +26,6 @@ import org.junit.Before import org.junit.Ignore import org.junit.Rule import org.junit.Test -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.components.toolbar.DefaultToolbarMenu import org.mozilla.fenix.ext.settings @@ -88,70 +87,62 @@ class DefaultToolbarMenuTest { @Test @Ignore("Intermittent test: https://github.com/mozilla-mobile/fenix/issues/18822") fun `WHEN the bottom toolbar is set THEN the first item in the list is not the navigation`() { - if (FeatureFlags.toolbarMenuFeature) { - every { context.settings().shouldUseBottomToolbar } returns true - createMenu() + every { context.settings().shouldUseBottomToolbar } returns true + createMenu() - val menuItems = toolbarMenu.newCoreMenuItems - assertNotNull(menuItems) + val menuItems = toolbarMenu.coreMenuItems + assertNotNull(menuItems) - val firstItem = menuItems[0] - val newTabItem = toolbarMenu.newTabItem + val firstItem = menuItems[0] + val newTabItem = toolbarMenu.newTabItem - assertEquals(newTabItem, firstItem) - } + assertEquals(newTabItem, firstItem) } @Test @Ignore("Intermittent test: https://github.com/mozilla-mobile/fenix/issues/18822") fun `WHEN the top toolbar is set THEN the first item in the list is the navigation`() { - if (FeatureFlags.toolbarMenuFeature) { - every { context.settings().shouldUseBottomToolbar } returns false - createMenu() + every { context.settings().shouldUseBottomToolbar } returns false + createMenu() - val menuItems = toolbarMenu.newCoreMenuItems - assertNotNull(menuItems) + val menuItems = toolbarMenu.coreMenuItems + assertNotNull(menuItems) - val firstItem = menuItems[0] - val navToolbar = toolbarMenu.menuToolbar + val firstItem = menuItems[0] + val navToolbar = toolbarMenu.menuToolbar - assertEquals(navToolbar, firstItem) - } + assertEquals(navToolbar, firstItem) } @Test @Ignore("Intermittent test: https://github.com/mozilla-mobile/fenix/issues/18822") fun `WHEN the bottom toolbar is set THEN the nav menu should be the last item`() { - if (FeatureFlags.toolbarMenuFeature) { - every { context.settings().shouldUseBottomToolbar } returns true + every { context.settings().shouldUseBottomToolbar } returns true - createMenu() + createMenu() - val menuItems = toolbarMenu.newCoreMenuItems - assertNotNull(menuItems) + val menuItems = toolbarMenu.coreMenuItems + assertNotNull(menuItems) - val lastItem = menuItems[menuItems.size - 1] - val navToolbar = toolbarMenu.menuToolbar + val lastItem = menuItems[menuItems.size - 1] + val navToolbar = toolbarMenu.menuToolbar - assertEquals(navToolbar, lastItem) - } + assertEquals(navToolbar, lastItem) } @Test @Ignore("Intermittent test: https://github.com/mozilla-mobile/fenix/issues/18822") fun `WHEN the top toolbar is set THEN settings should be the last item`() { - if (FeatureFlags.toolbarMenuFeature) { - every { context.settings().shouldUseBottomToolbar } returns false + every { context.settings().shouldUseBottomToolbar } returns false - createMenu() + createMenu() - val menuItems = toolbarMenu.newCoreMenuItems - assertNotNull(menuItems) + val menuItems = toolbarMenu.coreMenuItems + assertNotNull(menuItems) - val lastItem = menuItems[menuItems.size - 1] - val settingsItem = toolbarMenu.settingsItem + val lastItem = menuItems[menuItems.size - 1] + val settingsItem = toolbarMenu.settingsItem - assertEquals(settingsItem, lastItem) - } + assertEquals(settingsItem, lastItem) } } From 7d5582a5bf7f895d2212fbceecf9e3f95401ac97 Mon Sep 17 00:00:00 2001 From: Mozilla L10n Automation Bot Date: Thu, 3 Jun 2021 00:08:02 +0000 Subject: [PATCH 015/500] Import l10n. --- app/src/main/res/values-br/strings.xml | 3 +++ app/src/main/res/values-el/strings.xml | 2 +- app/src/main/res/values-gn/strings.xml | 29 ++++++++++++++++++++++++- app/src/main/res/values-rm/strings.xml | 3 +++ app/src/main/res/values-tzm/strings.xml | 2 ++ 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index ae23704ca6d3..97e43197adec 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -1596,6 +1596,9 @@ Dibrennit ho trevnad + + Dibrennit evit implijout titouroù kartenn gred enrollet + Ouzhpennañ ul lusker klask diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index c1ac7c130c29..d3c0ec2e2de1 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -1506,7 +1506,7 @@ Κωδικός πρόσβασης - Εισάγετε ξανά το PIN σας + Εισαγάγετε ξανά το PIN σας Ξεκλειδώστε για να δείτε τις αποθηκευμένες συνδέσεις σας diff --git a/app/src/main/res/values-gn/strings.xml b/app/src/main/res/values-gn/strings.xml index 5960304b555e..810a6e6ea04c 100644 --- a/app/src/main/res/values-gn/strings.xml +++ b/app/src/main/res/values-gn/strings.xml @@ -419,6 +419,11 @@ and the third is the device model. --> %1$s %2$s %3$s-pe + + Kuatia’atã ñemurã + + Kundaharape + Tendayke g̃uahẽmbyre @@ -1616,6 +1621,22 @@ Ikatúpiko ehai kuatia’atã ñemurã papapy oikóva + + Embojuruja ehecha hag̃ua kuatia’atã ñongatupyre + + Emohekorosã nde kuatia’atã ñemurã + + Emboheko peteĩ jekokoha rape, PIN térã ñe’ẽñemi emo’ã hag̃ua nde kuatia’atã ñongatupyre ambue oikeséramo ne mba’e’okápe. + + Emboheko ko’ág̃a + + Upéi + + Embojuruja ne mba’e’oka + + + Embojuruja eipuru hag̃ua kuatia’atã ñemurã marandu mbyatypyre + Embojuaju hekaha @@ -1786,4 +1807,10 @@ Eikutu ápe eikuaave hag̃ua - + + Eikundaha yvate gotyo + + + Mboty + + diff --git a/app/src/main/res/values-rm/strings.xml b/app/src/main/res/values-rm/strings.xml index 3761993bbf30..4ef2d5291579 100644 --- a/app/src/main/res/values-rm/strings.xml +++ b/app/src/main/res/values-rm/strings.xml @@ -1607,6 +1607,9 @@ Debloccar tes apparat + + Debloccar per utilisar las datas da cartas da credit memorisadas + Agiuntar ina maschina da tschertgar diff --git a/app/src/main/res/values-tzm/strings.xml b/app/src/main/res/values-tzm/strings.xml index e223d2be2711..625fc4a45ce6 100644 --- a/app/src/main/res/values-tzm/strings.xml +++ b/app/src/main/res/values-tzm/strings.xml @@ -89,6 +89,8 @@ Ɣef %1$s + + Tigurawin n uzerray Amiḍan From e4fa71fde7a7dcc6e1581547b4b18471e7f8c6d6 Mon Sep 17 00:00:00 2001 From: ZianeA Date: Sun, 4 Apr 2021 14:54:21 +0100 Subject: [PATCH 016/500] For #[15083]: Add multi select to recently closed tabs --- .../recentlyclosed/RecentlyClosedAdapter.kt | 20 +++- .../RecentlyClosedController.kt | 61 ++++++++-- .../recentlyclosed/RecentlyClosedFragment.kt | 86 +++++++++++---- .../RecentlyClosedFragmentInteractor.kt | 16 ++- .../RecentlyClosedFragmentStore.kt | 15 ++- .../RecentlyClosedFragmentView.kt | 39 ++++--- .../RecentlyClosedItemViewHolder.kt | 20 +++- .../res/layout/component_recently_closed.xml | 3 +- .../DefaultRecentlyClosedControllerTest.kt | 104 ++++++++++++++++-- .../RecentlyClosedFragmentInteractorTest.kt | 6 +- 10 files changed, 299 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedAdapter.kt index 67bd16500cb2..a3a6abb34a7b 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedAdapter.kt @@ -9,28 +9,42 @@ import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import mozilla.components.browser.state.state.recover.RecoverableTab +import org.mozilla.fenix.selection.SelectionHolder class RecentlyClosedAdapter( private val interactor: RecentlyClosedFragmentInteractor -) : ListAdapter(DiffCallback) { +) : ListAdapter(DiffCallback), + SelectionHolder { + + private var selectedTabs: Set = emptySet() + override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): RecentlyClosedItemViewHolder { val view = LayoutInflater.from(parent.context) .inflate(RecentlyClosedItemViewHolder.LAYOUT_ID, parent, false) - return RecentlyClosedItemViewHolder(view, interactor) + return RecentlyClosedItemViewHolder(view, interactor, this) } override fun onBindViewHolder(holder: RecentlyClosedItemViewHolder, position: Int) { holder.bind(getItem(position)) } + override val selectedItems: Set + get() = selectedTabs + + fun updateData(tabs: List, selectedTabs: Set) { + this.selectedTabs = selectedTabs + notifyItemRangeChanged(0, tabs.size) + submitList(tabs) + } + private object DiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: RecoverableTab, newItem: RecoverableTab) = oldItem.id == newItem.id override fun areContentsTheSame(oldItem: RecoverableTab, newItem: RecoverableTab) = - oldItem.id == newItem.id + oldItem == newItem } } diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedController.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedController.kt index 47f1b2935986..d1b3c18805d5 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedController.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedController.kt @@ -21,18 +21,27 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph +@Suppress("TooManyFunctions") interface RecentlyClosedController { - fun handleOpen(item: RecoverableTab, mode: BrowsingMode? = null) - fun handleDeleteOne(tab: RecoverableTab) + fun handleOpen(tab: RecoverableTab, mode: BrowsingMode? = null) + fun handleOpen(tabs: Set, mode: BrowsingMode? = null) + fun handleDelete(tab: RecoverableTab) + fun handleDelete(tabs: Set) fun handleCopyUrl(item: RecoverableTab) - fun handleShare(item: RecoverableTab) + fun handleShare(tab: RecoverableTab) + fun handleShare(tabs: Set) fun handleNavigateToHistory() fun handleRestore(item: RecoverableTab) + fun handleSelect(tab: RecoverableTab) + fun handleDeselect(tab: RecoverableTab) + fun handleBackPressed(): Boolean } +@Suppress("TooManyFunctions") class DefaultRecentlyClosedController( private val navController: NavController, - private val store: BrowserStore, + private val browserStore: BrowserStore, + private val recentlyClosedStore: RecentlyClosedFragmentStore, private val tabsUseCases: TabsUseCases, private val resources: Resources, private val snackbar: FenixSnackbar, @@ -40,12 +49,30 @@ class DefaultRecentlyClosedController( private val activity: HomeActivity, private val openToBrowser: (item: RecoverableTab, mode: BrowsingMode?) -> Unit ) : RecentlyClosedController { - override fun handleOpen(item: RecoverableTab, mode: BrowsingMode?) { - openToBrowser(item, mode) + override fun handleOpen(tab: RecoverableTab, mode: BrowsingMode?) { + openToBrowser(tab, mode) } - override fun handleDeleteOne(tab: RecoverableTab) { - store.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tab)) + override fun handleOpen(tabs: Set, mode: BrowsingMode?) { + recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll) + tabs.forEach { tab -> handleOpen(tab, mode) } + } + + override fun handleSelect(tab: RecoverableTab) { + recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Select(tab)) + } + + override fun handleDeselect(tab: RecoverableTab) { + recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Deselect(tab)) + } + + override fun handleDelete(tab: RecoverableTab) { + browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tab)) + } + + override fun handleDelete(tabs: Set) { + recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll) + tabs.forEach { tab -> handleDelete(tab) } } override fun handleNavigateToHistory() { @@ -64,10 +91,13 @@ class DefaultRecentlyClosedController( } } - override fun handleShare(item: RecoverableTab) { + override fun handleShare(tab: RecoverableTab) = handleShare(setOf(tab)) + + override fun handleShare(tabs: Set) { + val shareData = tabs.map { ShareData(url = it.url, title = it.title) } navController.navigateBlockingForAsyncNavGraph( RecentlyClosedFragmentDirections.actionGlobalShareFragment( - data = arrayOf(ShareData(url = item.url, title = item.title)) + data = shareData.toTypedArray() ) ) } @@ -75,7 +105,7 @@ class DefaultRecentlyClosedController( override fun handleRestore(item: RecoverableTab) { tabsUseCases.restore(item) - store.dispatch( + browserStore.dispatch( RecentlyClosedAction.RemoveClosedTabAction(item) ) @@ -83,4 +113,13 @@ class DefaultRecentlyClosedController( from = BrowserDirection.FromRecentlyClosed ) } + + override fun handleBackPressed(): Boolean { + return if (recentlyClosedStore.state.selectedTabs.isNotEmpty()) { + recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll) + true + } else { + false + } + } } diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt index 01e2188f63f9..7505df7e956f 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.library.recentlyclosed import android.content.ClipboardManager import android.content.Context import android.os.Bundle +import android.text.SpannableString import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater @@ -21,6 +22,7 @@ import kotlinx.coroutines.flow.map import mozilla.components.browser.state.state.recover.RecoverableTab import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.lib.state.ext.flowScoped +import mozilla.components.support.base.feature.UserInteractionHandler import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity @@ -30,17 +32,19 @@ import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.ext.getRootView import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.ext.setTextColor import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.library.LibraryPageFragment @Suppress("TooManyFunctions") -class RecentlyClosedFragment : LibraryPageFragment() { +class RecentlyClosedFragment : LibraryPageFragment(), UserInteractionHandler { private lateinit var recentlyClosedFragmentStore: RecentlyClosedFragmentStore private var _recentlyClosedFragmentView: RecentlyClosedFragmentView? = null protected val recentlyClosedFragmentView: RecentlyClosedFragmentView get() = _recentlyClosedFragmentView!! private lateinit var recentlyClosedInteractor: RecentlyClosedFragmentInteractor + private lateinit var recentlyClosedController: RecentlyClosedController override fun onResume() { super.onResume() @@ -48,15 +52,43 @@ class RecentlyClosedFragment : LibraryPageFragment() { } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.library_menu, menu) + if (recentlyClosedFragmentStore.state.selectedTabs.isNotEmpty()) { + inflater.inflate(R.menu.history_select_multi, menu) + menu.findItem(R.id.delete_history_multi_select)?.let { deleteItem -> + deleteItem.title = SpannableString(deleteItem.title) + .apply { setTextColor(requireContext(), R.attr.destructive) } + } + } else { + inflater.inflate(R.menu.library_menu, menu) + } } - override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { - R.id.close_history -> { - close() - true + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val selectedTabs = recentlyClosedFragmentStore.state.selectedTabs + + return when (item.itemId) { + R.id.close_history -> { + close() + true + } + R.id.share_history_multi_select -> { + recentlyClosedController.handleShare(selectedTabs) + true + } + R.id.delete_history_multi_select -> { + recentlyClosedController.handleDelete(selectedTabs) + true + } + R.id.open_history_in_new_tabs_multi_select -> { + recentlyClosedController.handleOpen(selectedTabs, BrowsingMode.Normal) + true + } + R.id.open_history_in_private_tabs_multi_select -> { + recentlyClosedController.handleOpen(selectedTabs, BrowsingMode.Private) + true + } + else -> super.onOptionsItemSelected(item) } - else -> super.onOptionsItemSelected(item) } override fun onCreate(savedInstanceState: Bundle?) { @@ -73,25 +105,26 @@ class RecentlyClosedFragment : LibraryPageFragment() { recentlyClosedFragmentStore = StoreProvider.get(this) { RecentlyClosedFragmentStore( RecentlyClosedFragmentState( - items = listOf() + items = listOf(), + selectedTabs = emptySet() ) ) } - recentlyClosedInteractor = RecentlyClosedFragmentInteractor( - recentlyClosedController = DefaultRecentlyClosedController( - navController = findNavController(), - store = requireComponents.core.store, - activity = activity as HomeActivity, - tabsUseCases = requireComponents.useCases.tabsUseCases, - resources = requireContext().resources, - snackbar = FenixSnackbar.make( - view = requireActivity().getRootView()!!, - isDisplayedWithBrowserToolbar = true - ), - clipboardManager = activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager, - openToBrowser = ::openItem - ) + recentlyClosedController = DefaultRecentlyClosedController( + navController = findNavController(), + browserStore = requireComponents.core.store, + recentlyClosedStore = recentlyClosedFragmentStore, + activity = activity as HomeActivity, + tabsUseCases = requireComponents.useCases.tabsUseCases, + resources = requireContext().resources, + snackbar = FenixSnackbar.make( + view = requireActivity().getRootView()!!, + isDisplayedWithBrowserToolbar = true + ), + clipboardManager = activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager, + openToBrowser = ::openItem ) + recentlyClosedInteractor = RecentlyClosedFragmentInteractor(recentlyClosedController) _recentlyClosedFragmentView = RecentlyClosedFragmentView( view.recentlyClosedLayout, recentlyClosedInteractor @@ -116,8 +149,9 @@ class RecentlyClosedFragment : LibraryPageFragment() { @ExperimentalCoroutinesApi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - consumeFrom(recentlyClosedFragmentStore) { - recentlyClosedFragmentView.update(it.items) + consumeFrom(recentlyClosedFragmentStore) { state -> + recentlyClosedFragmentView.update(state) + activity?.invalidateOptionsMenu() } requireComponents.core.store.flowScoped(viewLifecycleOwner) { flow -> @@ -132,4 +166,8 @@ class RecentlyClosedFragment : LibraryPageFragment() { } override val selectedItems: Set = setOf() + + override fun onBackPressed(): Boolean { + return recentlyClosedController.handleBackPressed() + } } diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractor.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractor.kt index a4ffed2dc2b4..8c1469adea0c 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractor.kt @@ -34,11 +34,23 @@ class RecentlyClosedFragmentInteractor( recentlyClosedController.handleOpen(item, BrowsingMode.Private) } - override fun onDeleteOne(tab: RecoverableTab) { - recentlyClosedController.handleDeleteOne(tab) + override fun onDelete(tab: RecoverableTab) { + recentlyClosedController.handleDelete(tab) } override fun onNavigateToHistory() { recentlyClosedController.handleNavigateToHistory() } + + override fun open(item: RecoverableTab) { + recentlyClosedController.handleRestore(item) + } + + override fun select(item: RecoverableTab) { + recentlyClosedController.handleSelect(item) + } + + override fun deselect(item: RecoverableTab) { + recentlyClosedController.handleDeselect(item) + } } diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentStore.kt index 37b4d14c09ac..849f6bcd0324 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentStore.kt @@ -24,13 +24,19 @@ class RecentlyClosedFragmentStore(initialState: RecentlyClosedFragmentState) : */ sealed class RecentlyClosedFragmentAction : Action { data class Change(val list: List) : RecentlyClosedFragmentAction() + data class Select(val tab: RecoverableTab) : RecentlyClosedFragmentAction() + data class Deselect(val tab: RecoverableTab) : RecentlyClosedFragmentAction() + object DeselectAll : RecentlyClosedFragmentAction() } /** * The state for the Recently Closed Screen * @property items List of recently closed tabs to display */ -data class RecentlyClosedFragmentState(val items: List = emptyList()) : State +data class RecentlyClosedFragmentState( + val items: List = emptyList(), + val selectedTabs: Set +) : State /** * The RecentlyClosedFragmentState Reducer. @@ -41,5 +47,12 @@ private fun recentlyClosedStateReducer( ): RecentlyClosedFragmentState { return when (action) { is RecentlyClosedFragmentAction.Change -> state.copy(items = action.list) + is RecentlyClosedFragmentAction.Select -> { + state.copy(selectedTabs = state.selectedTabs + action.tab) + } + is RecentlyClosedFragmentAction.Deselect -> { + state.copy(selectedTabs = state.selectedTabs - action.tab) + } + RecentlyClosedFragmentAction.DeselectAll -> state.copy(selectedTabs = emptySet()) } } diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt index 740e82fa001a..0b9054ee4c95 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt @@ -5,17 +5,19 @@ package org.mozilla.fenix.library.recentlyclosed import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.appcompat.content.res.AppCompatResources -import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.android.extensions.LayoutContainer +import androidx.recyclerview.widget.SimpleItemAnimator import kotlinx.android.synthetic.main.component_recently_closed.* import mozilla.components.browser.state.state.recover.RecoverableTab import org.mozilla.fenix.R +import org.mozilla.fenix.library.LibraryPageView +import org.mozilla.fenix.selection.SelectionInteractor -interface RecentlyClosedInteractor { +interface RecentlyClosedInteractor : SelectionInteractor { /** * Called when an item is tapped to restore it. * @@ -57,11 +59,11 @@ interface RecentlyClosedInteractor { fun onOpenInPrivateTab(item: RecoverableTab) /** - * Deletes one recently closed tab item. + * Called when recently closed tab is selected for deletion. * - * @param tab the recently closed tab item to delete. + * @param tab the recently closed tab to delete. */ - fun onDeleteOne(tab: RecoverableTab) + fun onDelete(tab: RecoverableTab) } /** @@ -70,11 +72,10 @@ interface RecentlyClosedInteractor { class RecentlyClosedFragmentView( container: ViewGroup, private val interactor: RecentlyClosedFragmentInteractor -) : LayoutContainer { +) : LibraryPageView(container) { - override val containerView: ConstraintLayout = LayoutInflater.from(container.context) + val view: View = LayoutInflater.from(container.context) .inflate(R.layout.component_recently_closed, container, true) - .findViewById(R.id.recently_closed_wrapper) private val recentlyClosedAdapter: RecentlyClosedAdapter = RecentlyClosedAdapter(interactor) @@ -82,6 +83,7 @@ class RecentlyClosedFragmentView( recently_closed_list.apply { layoutManager = LinearLayoutManager(containerView.context) adapter = recentlyClosedAdapter + (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false } view_more_history.apply { @@ -102,9 +104,20 @@ class RecentlyClosedFragmentView( } } - fun update(items: List) { - recently_closed_empty_view.isVisible = items.isEmpty() - recently_closed_list.isVisible = items.isNotEmpty() - recentlyClosedAdapter.submitList(items) + fun update(state: RecentlyClosedFragmentState) { + state.apply { + recently_closed_empty_view.isVisible = items.isEmpty() + recently_closed_list.isVisible = items.isNotEmpty() + + recentlyClosedAdapter.updateData(items, selectedTabs) + + if (selectedTabs.isEmpty()) { + setUiForNormalMode(context.getString(R.string.library_recently_closed_tabs)) + } else { + setUiForSelectingMode( + context.getString(R.string.history_multi_select_title, selectedTabs.size) + ) + } + } } } diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt index 7d8e1f346682..03373a94de0f 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt @@ -7,14 +7,19 @@ package org.mozilla.fenix.library.recentlyclosed import android.view.View import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.history_list_item.view.* +import kotlinx.android.synthetic.main.library_site_item.view.* import mozilla.components.browser.state.state.recover.RecoverableTab import org.mozilla.fenix.R +import org.mozilla.fenix.ext.hideAndDisable +import org.mozilla.fenix.ext.showAndEnable +import org.mozilla.fenix.selection.SelectionHolder import org.mozilla.fenix.library.history.HistoryItemMenu import org.mozilla.fenix.utils.Do class RecentlyClosedItemViewHolder( view: View, - private val recentlyClosedFragmentInteractor: RecentlyClosedFragmentInteractor + private val recentlyClosedFragmentInteractor: RecentlyClosedFragmentInteractor, + private val selectionHolder: SelectionHolder ) : RecyclerView.ViewHolder(view) { private var item: RecoverableTab? = null @@ -30,12 +35,17 @@ class RecentlyClosedItemViewHolder( if (item.title.isNotEmpty()) item.title else item.url itemView.history_layout.urlView.text = item.url + itemView.history_layout.setSelectionInteractor(item, selectionHolder, recentlyClosedFragmentInteractor) + itemView.history_layout.changeSelected(item in selectionHolder.selectedItems) + if (this.item?.url != item.url) { itemView.history_layout.loadFavicon(item.url) } - itemView.setOnClickListener { - recentlyClosedFragmentInteractor.restore(item) + if (selectionHolder.selectedItems.isEmpty()) { + itemView.overflow_menu.showAndEnable() + } else { + itemView.overflow_menu.hideAndDisable() } this.item = item @@ -53,9 +63,7 @@ class RecentlyClosedItemViewHolder( HistoryItemMenu.Item.OpenInPrivateTab -> recentlyClosedFragmentInteractor.onOpenInPrivateTab( item ) - HistoryItemMenu.Item.Delete -> recentlyClosedFragmentInteractor.onDeleteOne( - item - ) + HistoryItemMenu.Item.Delete -> recentlyClosedFragmentInteractor.onDelete(item) } } diff --git a/app/src/main/res/layout/component_recently_closed.xml b/app/src/main/res/layout/component_recently_closed.xml index e0b70db2c4b3..feaf9e690e67 100644 --- a/app/src/main/res/layout/component_recently_closed.xml +++ b/app/src/main/res/layout/component_recently_closed.xml @@ -18,7 +18,8 @@ diff --git a/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/DefaultRecentlyClosedControllerTest.kt b/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/DefaultRecentlyClosedControllerTest.kt index 98825ea993de..07b2355c57f1 100644 --- a/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/DefaultRecentlyClosedControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/DefaultRecentlyClosedControllerTest.kt @@ -32,6 +32,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.ext.directionsEq +import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph import org.mozilla.fenix.ext.optionsEq import org.mozilla.fenix.helpers.FenixRobolectricTestRunner @@ -46,13 +47,15 @@ class DefaultRecentlyClosedControllerTest { private val clipboardManager: ClipboardManager = mockk(relaxed = true) private val openToBrowser: (RecoverableTab, BrowsingMode?) -> Unit = mockk(relaxed = true) private val activity: HomeActivity = mockk(relaxed = true) - private val store: BrowserStore = mockk(relaxed = true) + private val browserStore: BrowserStore = mockk(relaxed = true) + private val recentlyClosedStore: RecentlyClosedFragmentStore = mockk(relaxed = true) private val tabsUseCases: TabsUseCases = mockk(relaxed = true) val mockedTab: RecoverableTab = mockk(relaxed = true) private val controller = DefaultRecentlyClosedController( navController, - store, + browserStore, + recentlyClosedStore, tabsUseCases, resources, snackbar, @@ -89,13 +92,62 @@ class DefaultRecentlyClosedControllerTest { } @Test - fun handleDeleteOne() { + fun `open multiple tabs`() { + val tabs = createFakeTabList(2) + + controller.handleOpen(tabs.toSet(), BrowsingMode.Normal) + + verify { + openToBrowser(tabs[0], BrowsingMode.Normal) + openToBrowser(tabs[1], BrowsingMode.Normal) + } + + controller.handleOpen(tabs.toSet(), BrowsingMode.Private) + + verify { + openToBrowser(tabs[0], BrowsingMode.Private) + openToBrowser(tabs[1], BrowsingMode.Private) + } + } + + @Test + fun `handle select tab`() { + val selectedTab = createFakeTab() + + controller.handleSelect(selectedTab) + + verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Select(selectedTab)) } + } + + @Test + fun `handle deselect tab`() { + val deselectedTab = createFakeTab() + + controller.handleDeselect(deselectedTab) + + verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Deselect(deselectedTab)) } + } + + @Test + fun handleDelete() { val item: RecoverableTab = mockk(relaxed = true) - controller.handleDeleteOne(item) + controller.handleDelete(item) verify { - store.dispatch(RecentlyClosedAction.RemoveClosedTabAction(item)) + browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(item)) + } + } + + @Test + fun `delete multiple tabs`() { + val tabs = createFakeTabList(2) + + controller.handleDelete(tabs.toSet()) + + verify { + browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tabs[0])) + browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tabs[1])) } } @@ -104,7 +156,7 @@ class DefaultRecentlyClosedControllerTest { controller.handleNavigateToHistory() verify { - navController.navigate( + navController.navigateBlockingForAsyncNavGraph( directionsEq( RecentlyClosedFragmentDirections.actionGlobalHistoryFragment() ), @@ -139,7 +191,7 @@ class DefaultRecentlyClosedControllerTest { controller.handleShare(item) verify { - navController.navigate( + navController.navigateBlockingForAsyncNavGraph( directionsEq( RecentlyClosedFragmentDirections.actionGlobalShareFragment( data = arrayOf(ShareData(url = item.url, title = item.title)) @@ -149,6 +201,23 @@ class DefaultRecentlyClosedControllerTest { } } + @Test + fun `share multiple tabs`() { + val tabs = createFakeTabList(2) + + controller.handleShare(tabs.toSet()) + + verify { + val data = arrayOf( + ShareData(title = tabs[0].title, url = tabs[0].url), + ShareData(title = tabs[1].title, url = tabs[1].url) + ) + navController.navigateBlockingForAsyncNavGraph( + directionsEq(RecentlyClosedFragmentDirections.actionGlobalShareFragment(data)) + ) + } + } + @Test fun handleRestore() { controller.handleRestore(mockedTab) @@ -157,4 +226,25 @@ class DefaultRecentlyClosedControllerTest { verify { tabsUseCases.restore.invoke(mockedTab, true) } } + + @Test + fun `exist multi-select mode when back is pressed`() { + every { recentlyClosedStore.state.selectedTabs } returns createFakeTabList(3).toSet() + + controller.handleBackPressed() + + verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll) } + } + + private fun createFakeTab(id: String = "FakeId", url: String = "www.fake.com"): RecoverableTab = + RecoverableTab(id, url) + + private fun createFakeTabList(size: Int): List { + val fakeTabs = mutableListOf() + for (i in 0 until size) { + fakeTabs.add(createFakeTab(id = "FakeId$i")) + } + + return fakeTabs + } } diff --git a/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractorTest.kt index 934ce58eaae2..9ba2a9ee1e68 100644 --- a/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentInteractorTest.kt @@ -76,12 +76,12 @@ class RecentlyClosedFragmentInteractorTest { } @Test - fun onDeleteOne() { + fun onDelete() { val tab = RecoverableTab(id = "tab-id", title = "Mozilla", url = "mozilla.org", lastAccess = 1L) - interactor.onDeleteOne(tab) + interactor.onDelete(tab) verify { - defaultRecentlyClosedController.handleDeleteOne(tab) + defaultRecentlyClosedController.handleDelete(tab) } } From a5110f8c0aaf8c27919d63884ee3b5d852eec71a Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Thu, 3 Jun 2021 11:35:05 -0400 Subject: [PATCH 017/500] For #19746 - Remove FeatureFlags.nimbusExperiments (#19771) --- .../main/java/org/mozilla/fenix/FeatureFlags.kt | 5 ----- .../org/mozilla/fenix/components/Analytics.kt | 15 +++++---------- .../mozilla/fenix/settings/DataChoicesFragment.kt | 2 -- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index e61457462a80..25125bc0f3ad 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -14,11 +14,6 @@ object FeatureFlags { */ val pullToRefreshEnabled = Config.channel.isNightlyOrDebug - /** - * Enables the Nimbus experiments library. - */ - const val nimbusExperiments = true - /** * Enables the Addresses autofill feature. */ diff --git a/app/src/main/java/org/mozilla/fenix/components/Analytics.kt b/app/src/main/java/org/mozilla/fenix/components/Analytics.kt index d875dd63d832..af365fd00cb3 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Analytics.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Analytics.kt @@ -14,10 +14,8 @@ import mozilla.components.lib.crash.service.GleanCrashReporterService import mozilla.components.lib.crash.service.MozillaSocorroService import mozilla.components.lib.crash.service.SentryService import mozilla.components.service.nimbus.NimbusApi -import mozilla.components.service.nimbus.NimbusDisabled import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.ReleaseChannel @@ -25,7 +23,6 @@ import org.mozilla.fenix.components.metrics.AdjustMetricsService import org.mozilla.fenix.components.metrics.GleanMetricsService import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.experiments.createNimbus -import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.perf.lazyMonitored import org.mozilla.fenix.utils.Mockable @@ -59,9 +56,11 @@ class Analytics( // The name "Fenix" here matches the product name on Socorro and is unrelated to the actual app name: // https://bugzilla.mozilla.org/show_bug.cgi?id=1523284 - val socorroService = MozillaSocorroService(context, appName = "Fenix", + val socorroService = MozillaSocorroService( + context, appName = "Fenix", version = MOZ_APP_VERSION, buildId = MOZ_APP_BUILDID, vendor = MOZ_APP_VENDOR, - releaseChannel = MOZ_UPDATE_CHANNEL) + releaseChannel = MOZ_UPDATE_CHANNEL + ) services.add(socorroService) val intent = Intent(context, HomeActivity::class.java).apply { @@ -102,11 +101,7 @@ class Analytics( } val experiments: NimbusApi by lazyMonitored { - if (FeatureFlags.nimbusExperiments) { - createNimbus(context, BuildConfig.NIMBUS_ENDPOINT) - } else { - NimbusDisabled() - } + createNimbus(context, BuildConfig.NIMBUS_ENDPOINT) } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/DataChoicesFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/DataChoicesFragment.kt index eb0c11332697..ceb6b2ab6a66 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/DataChoicesFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/DataChoicesFragment.kt @@ -7,7 +7,6 @@ package org.mozilla.fenix.settings import android.os.Bundle import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreference -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.MetricServiceType import org.mozilla.fenix.ext.components @@ -72,7 +71,6 @@ class DataChoicesFragment : PreferenceFragmentCompat() { requirePreference(R.string.pref_key_experimentation).apply { isChecked = context.settings().isExperimentationEnabled - isVisible = FeatureFlags.nimbusExperiments onPreferenceChangeListener = SharedPreferenceUpdater() } } From 0455cc3cd4b47a7d6153caa794cc2eb8a99a98aa Mon Sep 17 00:00:00 2001 From: Mugurell Date: Thu, 3 Jun 2021 19:13:43 +0300 Subject: [PATCH 018/500] For #18877 - Support updated PromptRequest AC APIs (#19767) * For #18877 - Support updated PromptRequest AC APIs This issue stemming from a race condition is fully resolved in AC by adding support for having multiple prompts at a time. Fenix needs just a small change to support the AC refactoring. * Update Android Components version to 91.0.20210603145049 Co-authored-by: Arturo Mejia --- app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt | 4 ++-- buildSrc/src/main/java/AndroidComponents.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt index 419f5c43598c..f541701735ce 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -135,10 +135,10 @@ class ShareFragment : AppCompatDialogFragment() { args.sessionId ?.let { sessionId -> browserStore.state.findTabOrCustomTab(sessionId) } ?.let { tab -> - val promptRequest = tab.content.promptRequest + val promptRequest = tab.content.promptRequests.lastOrNull { it is PromptRequest.Share } if (promptRequest is PromptRequest.Share) { consume(promptRequest) - browserStore.dispatch(ContentAction.ConsumePromptRequestAction(tab.id)) + browserStore.dispatch(ContentAction.ConsumePromptRequestAction(tab.id, promptRequest)) } } } diff --git a/buildSrc/src/main/java/AndroidComponents.kt b/buildSrc/src/main/java/AndroidComponents.kt index dac45351844d..1959980bd0f9 100644 --- a/buildSrc/src/main/java/AndroidComponents.kt +++ b/buildSrc/src/main/java/AndroidComponents.kt @@ -3,5 +3,5 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ object AndroidComponents { - const val VERSION = "91.0.20210601143118" + const val VERSION = "91.0.20210603145049" } From 69e9e35fffd2213c1f43b8f362dfbc7197d795b4 Mon Sep 17 00:00:00 2001 From: Neha Binwal <67039214+neha-b2001@users.noreply.github.com> Date: Fri, 4 Jun 2021 00:24:05 +0530 Subject: [PATCH 019/500] Increased text contrast ratio of TextViews in 'Share tab' (#18880) - Changed share_tab_url color to @color/photonLightGrey60 - Changed appName and recent_apps_link_header color to @color/photonDarkGrey10 --- app/src/main/res/layout/app_share_list_item.xml | 1 + app/src/main/res/layout/share_tab_item.xml | 2 +- app/src/main/res/values/styles.xml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/app_share_list_item.xml b/app/src/main/res/layout/app_share_list_item.xml index 09d7c16972ae..5a61b3ba7531 100644 --- a/app/src/main/res/layout/app_share_list_item.xml +++ b/app/src/main/res/layout/app_share_list_item.xml @@ -33,6 +33,7 @@ android:gravity="center|top" android:lines="2" android:textAlignment="gravity" + android:textColor="@color/photonDarkGrey10" android:textSize="10sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/share_tab_item.xml b/app/src/main/res/layout/share_tab_item.xml index 48315f2f2cc0..8ac1b1faa292 100644 --- a/app/src/main/res/layout/share_tab_item.xml +++ b/app/src/main/res/layout/share_tab_item.xml @@ -42,7 +42,7 @@ android:textSize="12sp" android:maxLines="1" android:ellipsize="end" - android:textColor="?secondaryText" + android:textColor="@color/photonLightGrey60" tools:text="https://www.mozilla.org/en-US/firefox/new/" app:layout_constraintStart_toStartOf="@id/share_tab_title" app:layout_constraintTop_toBottomOf="@id/share_tab_title" diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9d6230374850..828b802dbdf0 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -521,7 +521,7 @@ + + + + + + + + + + + + + + + + + + + + + + +