Merge "Change storage size before starting test" am: 960a21867c am: ab4ae8b8fb
am: 097af7adc2
Change-Id: Ia2e34139140dec3a5795438db35f795cac075e40
diff --git a/Android.mk b/Android.mk
index 1c4369c..8e1cbf4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,36 +1,41 @@
LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_PRIVILEGED_MODULE := true
+########################
+# Complete DocumentsUI app:
+include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES += guava
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- android-support-v4 \
- android-support-v7-appcompat \
- android-support-v13 \
- android-support-design \
- android-support-transition \
- android-support-v7-recyclerview
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JACK_FLAGS := \
- -D jack.optimization.inner-class.accessors=true
-
-# Only enable asserts on userdebug/eng builds
-ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
-LOCAL_JACK_FLAGS += -D jack.assert.policy=always
-endif
-
LOCAL_PACKAGE_NAME := DocumentsUI
-LOCAL_CERTIFICATE := platform
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_FULL_MANIFEST_FILE := $(LOCAL_PATH)/AndroidManifest.xml
-include $(BUILD_PACKAGE)
+include $(LOCAL_PATH)/build_apk.mk
+
+########################
+# Minimal DocumentsUI app (supports Scoped Directory Access only):
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/com/android/documentsui/ScopedAccessActivity.java \
+ src/com/android/documentsui/ScopedAccessPackageReceiver.java \
+ src/com/android/documentsui/ScopedAccessProvider.java \
+ src/com/android/documentsui/ScopedAccessMetrics.java \
+ src/com/android/documentsui/archives/Archive.java \
+ src/com/android/documentsui/archives/ArchiveId.java \
+ src/com/android/documentsui/archives/ArchivesProvider.java \
+ src/com/android/documentsui/archives/Loader.java \
+ src/com/android/documentsui/archives/Proxy.java \
+ src/com/android/documentsui/archives/ReadableArchive.java \
+ src/com/android/documentsui/archives/WriteableArchive.java \
+ src/com/android/documentsui/base/Providers.java \
+ src/com/android/documentsui/prefs/ScopedAccessLocalPreferences.java
+
+LOCAL_PACKAGE_NAME := DocumentsUIMinimal
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/minimal/res
+LOCAL_FULL_MANIFEST_FILE := $(LOCAL_PATH)/minimal/AndroidManifest.xml
+
+include $(LOCAL_PATH)/build_apk.mk
+
+# Include makefiles for tests and libraries under the current path
include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 716e611..f594660 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,3 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2007-2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.documentsui">
@@ -59,7 +77,7 @@
<activity
android:name=".inspector.InspectorActivity"
- android:label="@string/menu_inspector"
+ android:label="@string/menu_inspect"
android:icon="@drawable/launcher_icon"
android:theme="@style/DocumentsTheme">
</activity>
@@ -107,7 +125,7 @@
</activity-alias>
<activity
- android:name=".OpenExternalDirectoryActivity"
+ android:name=".ScopedAccessActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.os.storage.action.OPEN_EXTERNAL_DIRECTORY" />
@@ -116,6 +134,13 @@
</activity>
<provider
+ android:name=".ScopedAccessProvider"
+ android:authorities="com.android.documentsui.scopedAccess"
+ android:permission="android.permission.MANAGE_SCOPED_ACCESS_DIRECTORY_PERMISSIONS"
+ android:exported="true">
+ </provider>
+
+ <provider
android:name=".picker.LastAccessedProvider"
android:authorities="com.android.documentsui.lastAccessed"
android:exported="false"/>
@@ -153,5 +178,15 @@
android:exported="false"
android:process=":com.android.documentsui.services">
</service>
+
+ <activity
+ android:name=".selection.demo.SelectionDemoActivity"
+ android:label="Selection Demo"
+ android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/app-perf-tests/Android.mk b/app-perf-tests/Android.mk
index 3f6dd97..4db20a7 100644
--- a/app-perf-tests/Android.mk
+++ b/app-perf-tests/Android.mk
@@ -6,12 +6,11 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
LOCAL_STATIC_ANDROID_LIBRARIES := android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES := \
mockito-target \
- ub-uiautomator \
- legacy-android-test
+ ub-uiautomator
LOCAL_USE_AAPT2 := true
LOCAL_PACKAGE_NAME := DocumentsUIAppPerfTests
diff --git a/build_apk.mk b/build_apk.mk
new file mode 100644
index 0000000..c09517f
--- /dev/null
+++ b/build_apk.mk
@@ -0,0 +1,28 @@
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_STATIC_JAVA_LIBRARIES += guava
+
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+ android-support-core-ui \
+ android-support-v4 \
+ android-support-v7-appcompat \
+ android-support-v13 \
+ android-support-design \
+ android-support-transition \
+ android-support-v7-recyclerview
+
+LOCAL_USE_AAPT2 := true
+
+LOCAL_JACK_FLAGS := \
+ -D jack.optimization.inner-class.accessors=true
+
+# Only enable asserts on userdebug/eng builds
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+LOCAL_JACK_FLAGS += -D jack.assert.policy=always
+endif
+
+LOCAL_CERTIFICATE := platform
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+include $(BUILD_PACKAGE)
diff --git a/minimal/AndroidManifest.xml b/minimal/AndroidManifest.xml
new file mode 100644
index 0000000..fd12939
--- /dev/null
+++ b/minimal/AndroidManifest.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2007-2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.documentsui">
+
+ <uses-permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS" />
+ <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
+ <uses-permission android:name="android.permission.CACHE_CONTENT" />
+
+ <!-- This is a minimal version of the DocumentsUI app supporting ScopedDirectoryAccess
+ only. It is part of the Android TV build. -->
+ <application
+ android:label="@string/app_label"
+ android:icon="@drawable/app_icon"
+ android:supportsRtl="true"
+ android:allowBackup="false"
+ android:fullBackupOnly="false">
+
+ <activity
+ android:name=".ScopedAccessActivity"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.os.storage.action.OPEN_EXTERNAL_DIRECTORY" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <receiver android:name=".ScopedAccessPackageReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
+ <action android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
+ <data android:scheme="package" />
+ </intent-filter>
+ </receiver>
+
+ <provider
+ android:name=".ScopedAccessProvider"
+ android:authorities="com.android.documentsui.scopedAccess"
+ android:permission="android.permission.MANAGE_SCOPED_ACCESS_DIRECTORY_PERMISSIONS"
+ android:exported="true">
+ </provider>
+
+ </application>
+</manifest>
diff --git a/minimal/res/layout/dialog_open_scoped_directory.xml b/minimal/res/layout/dialog_open_scoped_directory.xml
new file mode 100644
index 0000000..cb39206
--- /dev/null
+++ b/minimal/res/layout/dialog_open_scoped_directory.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:theme="@style/Theme.AppCompat.Light.Dialog.Alert"
+ android:orientation="vertical"
+ android:paddingEnd="24dp"
+ android:paddingStart="24dp" >
+
+ <TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingEnd="24dp"
+ android:paddingStart="32dp"
+ android:paddingTop="24dp">
+ </TextView>
+
+ <CheckBox
+ android:id="@+id/do_not_ask_checkbox"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dip"
+ android:text="@string/never_ask_again"
+ android:textColor="?android:attr/textColorSecondary"
+ android:visibility="gone" />
+</LinearLayout>
diff --git a/minimal/res/mipmap-anydpi/ic_app_icon.xml b/minimal/res/mipmap-anydpi/ic_app_icon.xml
new file mode 100644
index 0000000..cd4fa58
--- /dev/null
+++ b/minimal/res/mipmap-anydpi/ic_app_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/app_icon_background"/>
+ <foreground android:drawable="@mipmap/ic_launcher_icon_foreground"/>
+</adaptive-icon>
diff --git a/minimal/res/mipmap-hdpi/ic_launcher_icon_foreground.png b/minimal/res/mipmap-hdpi/ic_launcher_icon_foreground.png
new file mode 100644
index 0000000..992c44e
--- /dev/null
+++ b/minimal/res/mipmap-hdpi/ic_launcher_icon_foreground.png
Binary files differ
diff --git a/minimal/res/mipmap-mdpi/ic_launcher_icon_foreground.png b/minimal/res/mipmap-mdpi/ic_launcher_icon_foreground.png
new file mode 100644
index 0000000..4639ff0
--- /dev/null
+++ b/minimal/res/mipmap-mdpi/ic_launcher_icon_foreground.png
Binary files differ
diff --git a/minimal/res/mipmap-xhdpi/ic_launcher_icon_foreground.png b/minimal/res/mipmap-xhdpi/ic_launcher_icon_foreground.png
new file mode 100644
index 0000000..b992944
--- /dev/null
+++ b/minimal/res/mipmap-xhdpi/ic_launcher_icon_foreground.png
Binary files differ
diff --git a/minimal/res/mipmap-xxhdpi/ic_launcher_icon_foreground.png b/minimal/res/mipmap-xxhdpi/ic_launcher_icon_foreground.png
new file mode 100644
index 0000000..ae44b2f
--- /dev/null
+++ b/minimal/res/mipmap-xxhdpi/ic_launcher_icon_foreground.png
Binary files differ
diff --git a/minimal/res/mipmap-xxxhdpi/ic_launcher_icon_foreground.png b/minimal/res/mipmap-xxxhdpi/ic_launcher_icon_foreground.png
new file mode 100644
index 0000000..85150eb
--- /dev/null
+++ b/minimal/res/mipmap-xxxhdpi/ic_launcher_icon_foreground.png
Binary files differ
diff --git a/minimal/res/values/colors.xml b/minimal/res/values/colors.xml
new file mode 100644
index 0000000..61a8150
--- /dev/null
+++ b/minimal/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <color name="app_icon_background">#ff4688f2</color>
+</resources>
diff --git a/minimal/res/values/drawables.xml b/minimal/res/values/drawables.xml
new file mode 100644
index 0000000..2e5e77d
--- /dev/null
+++ b/minimal/res/values/drawables.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <item name="app_icon" type="drawable">@mipmap/ic_app_icon</item>
+ <item name="launcher_icon" type="drawable">@mipmap/ic_app_icon</item>
+</resources>
diff --git a/minimal/res/values/strings.xml b/minimal/res/values/strings.xml
new file mode 100644
index 0000000..bcffd6b
--- /dev/null
+++ b/minimal/res/values/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title of the Files application [CHAR LIMIT=32] -->
+ <string name="files_label">Files</string>
+
+ <!-- Title of the documents application [CHAR LIMIT=32] -->
+ <string name="app_label">@string/files_label</string>
+
+ <!-- Title of the documents application [CHAR LIMIT=32] -->
+ <string name="launcher_label">@string/files_label</string>
+
+ <!-- Text in an alert dialog asking user to grant app access to a given directory in an external storage volume -->
+ <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
+ access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory on
+ <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string>
+ <!-- Text in an alert dialog asking user to grant app access to a given directory in the internal storage -->
+ <string name="open_external_dialog_request_primary_volume">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
+ access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory?</string>
+ <!-- Text in an alert dialog asking user to grant app access to all data in an external storage volume -->
+ <string name="open_external_dialog_root_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
+ access to your data, including photos and videos, on <xliff:g id="storage" example="SD Card"><i>^2</i></xliff:g>?</string>
+ <!-- Checkbox that allows user to not be questioned about the directory access request again -->
+ <string name="never_ask_again">Don\'t ask again</string>
+ <!-- Text in the button asking user to allow access to a given directory. -->
+ <string name="allow">Allow</string>
+ <!-- Text in the button asking user to deny access to a given directory. -->
+ <string name="deny">Deny</string>
+
+ <!-- Error message shown when an archive fails to load -->
+ <string name="archive_loading_failed">Unable to open archive for browsing. File is either corrupt, or an unsupported format.</string>
+
+</resources>
diff --git a/perf-tests/Android.mk b/perf-tests/Android.mk
index ac5537a..0f46966 100644
--- a/perf-tests/Android.mk
+++ b/perf-tests/Android.mk
@@ -8,14 +8,13 @@
$(call all-java-files-under, ../tests/common/com/android/documentsui) \
../tests/functional/com/android/documentsui/ActivityTest.java
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
LOCAL_STATIC_ANDROID_LIBRARIES := android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES := \
mockito-target \
ub-uiautomator \
ub-janktesthelper \
- espresso-core \
- legacy-android-test
+ espresso-core
LOCAL_USE_AAPT2 := true
LOCAL_PACKAGE_NAME := DocumentsUIPerfTests
diff --git a/res/color/selection_demo_item_selector.xml b/res/color/selection_demo_item_selector.xml
new file mode 100644
index 0000000..bd87b4c
--- /dev/null
+++ b/res/color/selection_demo_item_selector.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_activated="true"
+ android:color="?android:attr/colorForeground"
+ />
+ <item
+ android:state_activated="false"
+ android:color="?android:attr/colorForeground"
+ android:alpha=".3"
+ />
+</selector>
diff --git a/res/drawable-hdpi/ic_menu_share_alpha.png b/res/drawable-hdpi/ic_menu_share_am_alpha.png
similarity index 100%
rename from res/drawable-hdpi/ic_menu_share_alpha.png
rename to res/drawable-hdpi/ic_menu_share_am_alpha.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_share_alpha.png b/res/drawable-mdpi/ic_menu_share_am_alpha.png
similarity index 100%
rename from res/drawable-mdpi/ic_menu_share_alpha.png
rename to res/drawable-mdpi/ic_menu_share_am_alpha.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_share_alpha.png b/res/drawable-xhdpi/ic_menu_share_am_alpha.png
similarity index 100%
rename from res/drawable-xhdpi/ic_menu_share_alpha.png
rename to res/drawable-xhdpi/ic_menu_share_am_alpha.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_menu_share_alpha.png b/res/drawable-xxhdpi/ic_menu_share_am_alpha.png
similarity index 100%
rename from res/drawable-xxhdpi/ic_menu_share_alpha.png
rename to res/drawable-xxhdpi/ic_menu_share_am_alpha.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_menu_share_alpha.png b/res/drawable-xxxhdpi/ic_menu_share_am_alpha.png
similarity index 100%
rename from res/drawable-xxxhdpi/ic_menu_share_alpha.png
rename to res/drawable-xxxhdpi/ic_menu_share_am_alpha.png
Binary files differ
diff --git a/res/drawable/ic_menu_share.xml b/res/drawable/ic_menu_share.xml
index 927e7d3..d4a92c5 100644
--- a/res/drawable/ic_menu_share.xml
+++ b/res/drawable/ic_menu_share.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_share_alpha"
- android:tint="?android:attr/colorControlNormal" />
+ android:src="@drawable/ic_menu_share_am_alpha"
+ android:tint="?android:attr/colorControlNormal"
+ android:autoMirrored="true" />
diff --git a/res/drawable/inspector_separator.xml b/res/drawable/inspector_separator.xml
new file mode 100644
index 0000000..6a35283
--- /dev/null
+++ b/res/drawable/inspector_separator.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="10dp"
+ android:insetBottom="10dp" >
+ <shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <size android:height="1dp"/>
+ <solid android:color="@color/inspector_section_divider"/>
+ </shape>
+</inset>
\ No newline at end of file
diff --git a/res/drawable/selection_demo_band_overlay.xml b/res/drawable/selection_demo_band_overlay.xml
new file mode 100644
index 0000000..adf2b27
--- /dev/null
+++ b/res/drawable/selection_demo_band_overlay.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#339999ff" />
+ <stroke android:width="1dp" android:color="#44000000" />
+</shape>
diff --git a/res/drawable/selection_demo_item_background.xml b/res/drawable/selection_demo_item_background.xml
new file mode 100644
index 0000000..de5c142
--- /dev/null
+++ b/res/drawable/selection_demo_item_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_activated="true">
+ <color android:color="?android:attr/colorControlHighlight"></color>
+ </item>
+</selector>
diff --git a/res/layout/inspector_action_view.xml b/res/layout/inspector_action_view.xml
index 91418ae..4226383 100644
--- a/res/layout/inspector_action_view.xml
+++ b/res/layout/inspector_action_view.xml
@@ -23,8 +23,8 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/default_app_info"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="10dp"
@@ -33,12 +33,13 @@
<ImageView
android:id="@+id/app_icon"
android:paddingLeft="5dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_width="50dp"
+ android:layout_height="50dp" />
<TextView
android:id="@+id/app_name"
android:paddingLeft="16dp"
+ android:paddingBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/app_icon"
@@ -46,8 +47,8 @@
<ImageButton
android:id="@+id/inspector_action_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@null"/>
diff --git a/res/layout/document_inspector_activity.xml b/res/layout/inspector_activity.xml
similarity index 96%
rename from res/layout/document_inspector_activity.xml
rename to res/layout/inspector_activity.xml
index 65361de..f48bc92 100644
--- a/res/layout/document_inspector_activity.xml
+++ b/res/layout/inspector_activity.xml
@@ -21,7 +21,7 @@
<Toolbar
android:id="@+id/toolbar"
- android:title="Properties"
+ android:title="@string/inspector_title"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
diff --git a/res/layout/document_inspector_fragment.xml b/res/layout/inspector_fragment.xml
similarity index 89%
rename from res/layout/document_inspector_fragment.xml
rename to res/layout/inspector_fragment.xml
index 5edb5e0..24f0fdb 100644
--- a/res/layout/document_inspector_fragment.xml
+++ b/res/layout/inspector_fragment.xml
@@ -37,8 +37,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
+ <com.android.documentsui.inspector.MediaView
+ android:id="@+id/inspector_media_view"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
<com.android.documentsui.inspector.actions.ActionView
- android:paddingTop="10dp"
android:id="@+id/inspector_show_in_provider_view"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -46,7 +51,6 @@
android:visibility="gone"/>
<com.android.documentsui.inspector.actions.ActionView
- android:paddingTop="10dp"
android:id="@+id/inspector_app_defaults_view"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -58,6 +62,8 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingTop="20dp"
android:visibility="gone" />
+
</LinearLayout>
</ScrollView>
diff --git a/res/layout/inspector_header.xml b/res/layout/inspector_header.xml
index e293c12..d621801 100644
--- a/res/layout/inspector_header.xml
+++ b/res/layout/inspector_header.xml
@@ -23,15 +23,22 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.0"
- android:background="@android:color/black" />
+ android:background="@android:color/white" />
<TextView
android:id="@+id/inspector_file_title"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textSize="20dp"
- android:layout_alignBottom="@+id/inspector_thumbnail"
- android:paddingBottom="20dp"
- android:paddingLeft="18dp"
- android:textColor="@android:color/white" />
-</RelativeLayout>
\ No newline at end of file
+ android:textSize="20sp"
+ android:paddingTop="5dp"
+ android:paddingBottom="5dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:textColor="@android:color/white"
+ android:layout_gravity="center_vertical"
+ android:background="@color/inspector_title_background"
+ android:textIsSelectable="true"
+ android:textAlignment="viewStart"
+ android:layout_alignBottom="@+id/inspector_thumbnail" />
+
+</RelativeLayout>
diff --git a/res/layout/inspector_section_title.xml b/res/layout/inspector_section_title.xml
index 2804811..33889a8 100644
--- a/res/layout/inspector_section_title.xml
+++ b/res/layout/inspector_section_title.xml
@@ -14,16 +14,26 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="match_parent"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:paddingTop="10dp"
- android:paddingBottom="10dp"
- android:paddingLeft="16dp"
- android:layout_gravity="center_vertical"
- android:fontFamily="sans-serif-medium"
- android:textSize="14sp"
- android:textColor="@color/inspector_section_title">
+ android:orientation="vertical"
+ android:divider="@drawable/inspector_separator"
+ android:showDividers="beginning"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp">
-</TextView>
+ <TextView
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:id="@+id/inspector_header_title"
+ android:paddingStart="6dp"
+ android:paddingEnd="6dp"
+ android:paddingTop="5dp"
+ android:paddingBottom="5dp"
+ android:layout_gravity="center_vertical"
+ android:fontFamily="sans-serif-medium"
+ android:textSize="15sp"
+ android:textAlignment="viewStart"
+ android:textColor="@color/inspector_section_title"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/selection_demo_layout.xml b/res/layout/selection_demo_layout.xml
new file mode 100644
index 0000000..c4ed360
--- /dev/null
+++ b/res/layout/selection_demo_layout.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="?attr/colorPrimary"
+ android:elevation="4dp"
+ android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
+ />
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="0dp"
+ android:paddingEnd="0dp"
+ android:paddingTop="5dp"
+ android:paddingBottom="5dp"
+ android:clipToPadding="false"
+ android:scrollbars="none"
+ android:drawSelectorOnTop="true"
+ />
+
+</LinearLayout>
diff --git a/res/layout/selection_demo_list_item.xml b/res/layout/selection_demo_list_item.xml
new file mode 100644
index 0000000..0d4b718
--- /dev/null
+++ b/res/layout/selection_demo_list_item.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:paddingTop="5dp"
+ android:paddingBottom="5dp"
+ android:layout_height="50dp">
+ <LinearLayout
+ android:id="@+id/container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="@drawable/selection_demo_item_background">
+ <TextView
+ android:id="@+id/selector"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ android:gravity="center"
+ android:layout_height="match_parent"
+ android:layout_width="40dp"
+ android:textColor="@color/selection_demo_item_selector"
+ android:pointerIcon="hand"
+ android:text="✕">
+ </TextView>
+ <TextView
+ android:id="@+id/label"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ android:gravity="center_vertical"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+ </TextView>
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/table_key_value_row.xml b/res/layout/table_key_value_row.xml
index 2bc8cf6..b45cda4 100644
--- a/res/layout/table_key_value_row.xml
+++ b/res/layout/table_key_value_row.xml
@@ -21,15 +21,18 @@
android:layout_height="match_parent"
android:paddingTop="10dp"
android:paddingBottom="10dp"
- android:paddingLeft="16dp">
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp">
<TextView
android:id="@+id/table_row_key"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
+ android:paddingEnd="5dp"
android:textColor="@android:color/black"
- android:textSize="14dp">
+ android:textSize="14sp"
+ android:textAlignment="viewStart">
</TextView>
<TextView
@@ -38,7 +41,9 @@
android:layout_width="0dp"
android:layout_weight="1"
android:textColor="@color/inspector_value"
- android:textSize="14dp">
+ android:textSize="14sp"
+ android:textIsSelectable="true"
+ android:textAlignment="viewStart">
</TextView>
</com.android.documentsui.inspector.KeyValueRow>
diff --git a/res/menu/action_mode_menu.xml b/res/menu/action_mode_menu.xml
index ba23816..1952285 100644
--- a/res/menu/action_mode_menu.xml
+++ b/res/menu/action_mode_menu.xml
@@ -63,8 +63,8 @@
android:showAsAction="never"
android:visible="false" />
<item
- android:id="@+id/action_menu_inspector"
- android:title="@string/menu_inspector"
+ android:id="@+id/action_menu_inspect"
+ android:title="@string/menu_inspect"
android:showAsAction="never"
android:visible="false" />
<item
diff --git a/res/menu/activity.xml b/res/menu/activity.xml
index ce51e75..0c1e68c 100644
--- a/res/menu/activity.xml
+++ b/res/menu/activity.xml
@@ -77,5 +77,10 @@
android:title="@string/menu_settings"
android:showAsAction="never"
android:visible="false" />
+ <item
+ android:id="@+id/option_menu_inspect"
+ android:title="@string/menu_inspect"
+ android:showAsAction="never"
+ android:visible="false" />
</group>
</menu>
diff --git a/res/menu/container_context_menu.xml b/res/menu/container_context_menu.xml
index 08b0de8..2f70d82 100644
--- a/res/menu/container_context_menu.xml
+++ b/res/menu/container_context_menu.xml
@@ -35,4 +35,10 @@
android:id="@+id/dir_menu_select_all"
android:title="@string/menu_select_all" />
</group>
+ <group
+ android:id="@+id/menu_extras_group">
+ <item
+ android:id="@+id/dir_menu_inspect"
+ android:title="@string/menu_inspect" />
+ </group>
</menu>
\ No newline at end of file
diff --git a/res/menu/dir_context_menu.xml b/res/menu/dir_context_menu.xml
index 2950b53..383841a 100644
--- a/res/menu/dir_context_menu.xml
+++ b/res/menu/dir_context_menu.xml
@@ -47,4 +47,10 @@
android:id="@+id/dir_menu_delete"
android:title="@string/menu_delete" />
</group>
+ <group
+ android:id="@+id/menu_extras_group">
+ <item
+ android:id="@+id/dir_menu_inspect"
+ android:title="@string/menu_inspect" />
+ </group>
</menu>
diff --git a/res/menu/file_context_menu.xml b/res/menu/file_context_menu.xml
index 325bed9..9e786f1 100644
--- a/res/menu/file_context_menu.xml
+++ b/res/menu/file_context_menu.xml
@@ -50,7 +50,10 @@
android:title="@string/menu_delete" />
</group>
<group
- android:id="@+id/menu_settings_group">
+ android:id="@+id/menu_extras_group">
+ <item
+ android:id="@+id/dir_menu_inspect"
+ android:title="@string/menu_inspect" />
<item
android:id="@+id/dir_menu_view_in_owner"
android:title="@string/menu_view_in_owner" />
diff --git a/res/menu/mixed_context_menu.xml b/res/menu/mixed_context_menu.xml
index aa6d7f5..cb6b4fd 100644
--- a/res/menu/mixed_context_menu.xml
+++ b/res/menu/mixed_context_menu.xml
@@ -34,4 +34,10 @@
android:id="@+id/dir_menu_delete"
android:title="@string/menu_delete" />
</group>
+ <group
+ android:id="@+id/menu_extras_group">
+ <item
+ android:id="@+id/dir_menu_inspect"
+ android:title="@string/menu_inspect" />
+ </group>
</menu>
\ No newline at end of file
diff --git a/res/menu/selection_demo_actions.xml b/res/menu/selection_demo_actions.xml
new file mode 100644
index 0000000..e07c06b
--- /dev/null
+++ b/res/menu/selection_demo_actions.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/option_menu_add_column"
+ android:title="Add column"
+ android:showAsAction="always" />
+ <item
+ android:id="@+id/option_menu_remove_column"
+ android:title="Remove column"
+ android:showAsAction="always" />
+</menu>
diff --git a/res/values-af/inspector_strings.xml b/res/values-af/inspector_strings.xml
new file mode 100644
index 0000000..24dcc70
--- /dev/null
+++ b/res/values-af/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Inligting"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Lêerinligting kon nie gelaai word nie"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Ontfoutinligting (net ontwikkeling)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Onverwerkte metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Mediabesonderhede"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Hierdie soort lêer maak oop met"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Hierdie lêer word voorsien deur"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nie gekies nie"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Onbekend"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Afmetings"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koördinate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Hoogte bo seespieël"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Lensopening"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Sluiterspoed"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Tydsduur"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Geneem op"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Fokuslengte"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-ekwivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Kunstenaar"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Komponis"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Ligging"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stroomtipes"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Onverwerkte grootte (grepe)"</string>
+</resources>
diff --git a/res/values-af/mimes.xml b/res/values-af/mimes.xml
new file mode 100644
index 0000000..851e97b
--- /dev/null
+++ b/res/values-af/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-lêer"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Lêer"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Prent"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-prent"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Oudio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-oudio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-argief"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-program"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Skoonteks"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-aanbieding"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-sigblad"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-sigblad"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-aanbieding"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-skets"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-tabel"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-vorm"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-kaart"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-werf"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Vouer"</string>
+</resources>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 9dab308..4eb5f41 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Pers saam"</string>
<string name="menu_extract" msgid="8171946945982532262">"Onttrek na …"</string>
<string name="menu_rename" msgid="1883113442688817554">"Hernoem"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Eienskappe"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Kry inligting"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Bekyk in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nuwe venster"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Sny"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Skuif"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Maak toe"</string>
<string name="button_retry" msgid="4011461781916631389">"Probeer weer"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Vee uit"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Wys in verskaffer"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nie gerangskik nie"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Naam"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Opsomming"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipe"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Grootte"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Gewysig"</string>
- <string name="directory_children" msgid="8115290268549503262">"Aantal kinders"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Aantal items"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Stygend"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Dalend"</string>
<string name="drawer_open" msgid="8071673398187261741">"Wys wortels"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Kan lêer nie oopmaak nie"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Kan nie lêers in argiewe oopmaak nie"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Kan sommige dokumente nie uitvee nie"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Eienskappe kon nie gelaai word nie"</string>
<string name="share_via" msgid="8725082736005677161">"Deel via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopieer tans lêers"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Pers tans lêers saam"</string>
diff --git a/res/values-am/inspector_strings.xml b/res/values-am/inspector_strings.xml
new file mode 100644
index 0000000..423b6da
--- /dev/null
+++ b/res/values-am/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"መረጃ"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"የፋይል መረጃ ሊጫን አልቻለም"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"የማረሚያ መረጃ (ለገንቢ ብቻ)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"ጥሬ ዲበ ውሂብ፦ <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"የሚዲያ ዝርዝሮች"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"እንዲህ ዓይነቱ ፋይል በዚህ ይከፈታል፦"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ይህ ፋይል የቀረበው በ"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"አልተመረጠም"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"ያልታወቀ"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ልኬቶች"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> ሜፒ"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"መጋጠሚያዎች"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>፣ <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ከፍታ"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"ካሜራ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"የካሜራ ሌንስ መከለያ"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"የካሜራ ሌንስ መከለያ ፍጥነት"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"የቆይታ ጊዜ"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"የተነሳበት ቀን"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"የትክተት ርቀት"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> ሚሜ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"የአይኤስኦ እኩያ"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"አይኤስኦ <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"አርቲስት"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"የሙዚቃ ደራሲ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"አልበም"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"አካባቢ"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"የዥረት አይነቶች"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"የጥሬ መጠን (ባይት)"</string>
+</resources>
diff --git a/res/values-am/mimes.xml b/res/values-am/mimes.xml
new file mode 100644
index 0000000..a508032
--- /dev/null
+++ b/res/values-am/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"የ<xliff:g id="EXTENSION">%1$s</xliff:g> ፋይል"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ፋይል"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"ምስል"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"የ<xliff:g id="FILETYPE">%1$s</xliff:g> ምስል"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ኦዲዮ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"የ<xliff:g id="FILETYPE">%1$s</xliff:g> ኦዲዮ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ቪዲዮ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"የ<xliff:g id="FILETYPE">%1$s</xliff:g> ቪዲዮ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"የ<xliff:g id="FILETYPE">%1$s</xliff:g> ማህደር"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"የAndroid መተግበሪያ"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"ስነጣ አልባ ጽሑፍ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"የኤችቲኤምኤል ሰነድ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"የፒዲኤፍ ሰነድ"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"የWord ሰነድ"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"የPowerPoint ዝግጅት አቀራረብ"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"የExcel ተመን ሉህ"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"የGoogle ሰነድ"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"የGoogle ተመን ሉህ"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"የGoogle ዝግጅት አቀራረብ"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"የGoogle ስዕል"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"የGoogle ሠንጠረዥ"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"የGoogle ቅጽ"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"የGoogle ካርታ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"የGoogle ጣቢያ"</string>
+ <string name="directory_type" msgid="2702987727566226354">"አቃፊ"</string>
+</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index d52aa92..1cffb23 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"ጭመቅ"</string>
<string name="menu_extract" msgid="8171946945982532262">"አውጣ ወደ…"</string>
<string name="menu_rename" msgid="1883113442688817554">"ዳግም ሰይም"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"ባህሪያት"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"መረጃ አግኝ"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"በ<xliff:g id="SOURCE">%1$s</xliff:g> ይመልከቱ"</string>
<string name="menu_new_window" msgid="2947837751796109126">"አዲሰ መስኮት"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"ቁረጥ"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ውሰድ"</string>
<string name="button_dismiss" msgid="7235249361023803349">"አሰናብት"</string>
<string name="button_retry" msgid="4011461781916631389">"እንደገና ይሞክሩ"</string>
+ <string name="button_clear" msgid="5412304437764369441">"አጽዳ"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"በአቅራቢ ውስጥ አሳይ"</string>
<string name="not_sorted" msgid="7813496644889115530">"አልተደረደረም"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"ስም"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"ማጠቃለያ"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ዓይነት"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"መጠን"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"የተቀየረበት ጊዜ"</string>
- <string name="directory_children" msgid="8115290268549503262">"የሕፃናት ብዛት"</string>
+ <string name="directory_items" msgid="6645621978998614003">"የንጥሎች ብዛት"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ሽቅብታ"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"አቆልቋይ"</string>
<string name="drawer_open" msgid="8071673398187261741">"ስሮችን አሳይ"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ፋይሉን መክፈት አይቻልም"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"በማህደሮች ውስጥ ያሉ ፋይሎችን መክፈት አይቻልም"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"አንዳንድ ሰነዶችን መሰረዝ አልተቻለም"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"ባህሪዎቹ ሊጫኑ አልቻሉም"</string>
<string name="share_via" msgid="8725082736005677161">"በዚህ በኩል ያጋሩ፦"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ፋይሎችን በመቅዳት ላይ"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ፋይሎችን በመጭመቅ ላይ"</string>
diff --git a/res/values-ar/inspector_strings.xml b/res/values-ar/inspector_strings.xml
new file mode 100644
index 0000000..ffae9de
--- /dev/null
+++ b/res/values-ar/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"المعلومات"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"تعذّر تحميل معلومات الملف"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"معلومات تصحيح الأخطاء (المطوّر فقط)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"البيانات الوصفية الأولية: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"تفاصيل الوسائط"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"يتم فتح هذا النوع من الملفات باستخدام"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"تم تقديم هذا الملف من خلال"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"غير محدّد"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"غير معروف"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"الأبعاد"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> ميغا بكسل"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"إحداثيات"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>، <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"الارتفاع"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"الكاميرا"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"فتحة العدسة"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"سرعة مصراع الكاميرا"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"المدة"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"تم الالتقاط في"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"البعد البؤري"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> ملليمتر"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"مكافئ ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"سرعة ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"الفنان"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"الملحّن"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"الألبوم"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"الموقع الجغرافي"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"أنواع سلسلة البطاقات"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"الحجم الأولي (بالبايت)"</string>
+</resources>
diff --git a/res/values-ar/mimes.xml b/res/values-ar/mimes.xml
new file mode 100644
index 0000000..7f5b0ac
--- /dev/null
+++ b/res/values-ar/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"ملف <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ملف"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"صورة"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"صورة <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"صوت"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"صوت <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"فيديو"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"فيديو <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"أرشيف <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"تطبيق Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"نص عادي"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"مستند HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"مستند PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"مستند Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"عرض تقديمي في PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"جدول بيانات Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"مستند Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"جدول بيانات Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"عرض تقديمي على Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"رسم Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"جدول Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"نموذج Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"خريطة Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"موقع مصمم في مواقع Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"مجلد"</string>
+</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 3f3a334..4199682 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"ضغط"</string>
<string name="menu_extract" msgid="8171946945982532262">"الاستخراج إلى…"</string>
<string name="menu_rename" msgid="1883113442688817554">"إعادة تسمية"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"الخصائص"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"الحصول على المعلومات"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"العرض في <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"نافذة جديدة"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"قص"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"نقل"</string>
<string name="button_dismiss" msgid="7235249361023803349">"تجاهل"</string>
<string name="button_retry" msgid="4011461781916631389">"إعادة المحاولة"</string>
+ <string name="button_clear" msgid="5412304437764369441">"محو"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"عرض في مقدم الخدمة"</string>
<string name="not_sorted" msgid="7813496644889115530">"بدون ترتيب"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"الاسم"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"الملخص"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"النوع"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"الحجم"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"آخر تعديل"</string>
- <string name="directory_children" msgid="8115290268549503262">"عدد الأطفال"</string>
+ <string name="directory_items" msgid="6645621978998614003">"عدد العناصر"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"تصاعدي"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"تنازلي"</string>
<string name="drawer_open" msgid="8071673398187261741">"عرض الجذور"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"يتعذر فتح الملف"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"يتعذر فتح الملفات في الأرشيف"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"تعذر حذف بعض المستندات"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"تعذَّر تحميل الخصائص"</string>
<string name="share_via" msgid="8725082736005677161">"مشاركة عبر"</string>
<string name="copy_notification_title" msgid="52256435625098456">"جارٍ نسخ الملفات"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ضغط الملفات"</string>
@@ -228,8 +229,8 @@
<item quantity="one">تم نسخ ملف واحد (<xliff:g id="COUNT_0">%1$d</xliff:g>) إلى الحافظة.</item>
</plurals>
<string name="file_operation_rejected" msgid="4301554203329008794">"معالجة الملف غير متوافقة."</string>
- <string name="file_operation_error" msgid="2234357335716533795">"أخفقت معالجة الملف."</string>
- <string name="rename_error" msgid="6700093173508118635">"أخفقت إعادة تسمية المستند."</string>
+ <string name="file_operation_error" msgid="2234357335716533795">"تعذّرت معالجة الملف."</string>
+ <string name="rename_error" msgid="6700093173508118635">"تعذّرت إعادة تسمية المستند."</string>
<string name="menu_eject_root" msgid="9215040039374893613">"إخراج"</string>
<string name="notification_copy_files_converted_title" msgid="6916768494891833365">"تم تحويل بعض الملفات"</string>
<string name="open_external_dialog_request" msgid="8173558471322861268">"هل تريد منح التطبيق <xliff:g id="APPNAME"><b>^1</b></xliff:g> حق الوصول إلى الدليل <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> على <xliff:g id="STORAGE"><i>^3</i></xliff:g>؟"</string>
diff --git a/res/values-az/inspector_strings.xml b/res/values-az/inspector_strings.xml
new file mode 100644
index 0000000..2ae8084
--- /dev/null
+++ b/res/values-az/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Məlumat"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Fayl məlumatını yükləmək mümkün olmadı"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Sazlama haqqında məlumat (yalnız dev)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Sətir metadatası: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Media haqqında məlumat"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Bu fayl növü bele açılmalıdır"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Bu fayl təmin edilib"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Seçilməyib"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Naməlum"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Ölçülər"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinatlar"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Yüksəklik"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Dəlik"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Sürgü sürəti"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Müddət:"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Şəkil çəkilib"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Fokal uzunluq"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalenti"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"İfaçı"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Bəstəkar"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albom"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Məkan"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Axın növləri"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Sətir ölçüsü (bayt)"</string>
+</resources>
diff --git a/res/values-az/mimes.xml b/res/values-az/mimes.xml
new file mode 100644
index 0000000..7eeb0d3
--- /dev/null
+++ b/res/values-az/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> fayl"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fayl"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Şəkil"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> şəkli"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> arxiv faylı"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android tətbiqi"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Adi mətn"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML sənədi"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF sənədi"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word sənədi"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint təqdimatı"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel cədvəli"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google sənədi"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google cədvəli"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google təqdimatı"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google rəsm faylı"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google cədvəli"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google forması"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google xəritəsi"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google saytı"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Qovluq"</string>
+</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 851717e..c9046d7 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Sıxışdırın"</string>
<string name="menu_extract" msgid="8171946945982532262">"Çıxarın…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Adını dəyişdirin"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Xüsusiyyətlər"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Məlumat əldə edin"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> mənbəsində baxın"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Yeni pəncərə"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Kəsin"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Köçürün"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Yığışdırın"</string>
<string name="button_retry" msgid="4011461781916631389">"Yenidən cəhd edin"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Silin"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Provayderdə göstərin"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sıralanmayıb"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Ad"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Yekun"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Növ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Ölçü"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Dəyişmiş"</string>
- <string name="directory_children" msgid="8115290268549503262">"Uşaqların Sayı"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Elementlərin sayı"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Artan sıra ilə"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Azalan sıra ilə"</string>
<string name="drawer_open" msgid="8071673398187261741">"Kökləri göstərin"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Fayl açılmır"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Arxivdəki faylları açmaq olmur"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Bəzi sənədləri silə bilmir"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Xüsusiyyətləri yükləmək mümkün olmadı"</string>
<string name="share_via" msgid="8725082736005677161">"Bunun vasitəsilə paylaş:"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Fayllar kopyalanır"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Faylların sıxılması"</string>
diff --git a/res/values-b+sr+Latn/inspector_strings.xml b/res/values-b+sr+Latn/inspector_strings.xml
new file mode 100644
index 0000000..133f533
--- /dev/null
+++ b/res/values-b+sr+Latn/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informacije"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Učitavanje podataka o datoteci nije uspelo"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Podaci o otklanjanju grešaka (samo za programere)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metapodaci RAW datoteke: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalji o medijima"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ova vrsta datoteke se otvara pomoću:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Ovu datoteku pruža"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nije izabrano"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Nepoznato"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimenzije"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g>×<xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> megapiksela"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Nadmorska visina"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Otvor blende"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Brzina zatvarača"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Trajanje"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Snimljeno"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Žižna daljina"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Izvođač"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Kompozitor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokacija"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipovi strimova"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Veličina RAW datoteke (u bajtovima)"</string>
+</resources>
diff --git a/res/values-b+sr+Latn/mimes.xml b/res/values-b+sr+Latn/mimes.xml
new file mode 100644
index 0000000..a4e7bda
--- /dev/null
+++ b/res/values-b+sr+Latn/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> datoteka"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Datoteka"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Slika"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> slika"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> arhiva"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android aplikacija"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Običan tekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint prezentacija"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel tabela"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google tabela"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google prezentacija"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google crtež"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google tabela"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google upitnik"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google mapa"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google sajt"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Direktorijum"</string>
+</resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index f6b43e2..01d74db 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Komprimuj"</string>
<string name="menu_extract" msgid="8171946945982532262">"Izdvoj u…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Preimenuj"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Svojstva"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Prikaži informacije"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Prikaži u: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Novi prozor"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Iseci"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Premesti"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Odbaci"</string>
<string name="button_retry" msgid="4011461781916631389">"Probaj ponovo"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Obriši"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Prikaži u aplikaciji dobavljača"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nisu sortirani"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Naziv"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Rezime"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tip"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Veličina"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Izmenjeno"</string>
- <string name="directory_children" msgid="8115290268549503262">"Broj dece"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Broj stavki"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Rastuće"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Opadajuće"</string>
<string name="drawer_open" msgid="8071673398187261741">"Prikaži osnovne direktorijume"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Otvaranje datoteke nije uspelo"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Ne možete da otvarate datoteke u arhivama"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nije moguće izbrisati neke dokumente"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Učitavanje svojstava nije uspelo"</string>
<string name="share_via" msgid="8725082736005677161">"Deljenje preko"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopiramo datoteke"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Datoteke se komprimuju"</string>
diff --git a/res/values-be/inspector_strings.xml b/res/values-be/inspector_strings.xml
new file mode 100644
index 0000000..79cd4f2
--- /dev/null
+++ b/res/values-be/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Інфармацыя"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Не атрымалася загрузіць звесткі пра файл"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Адладачная інф-цыя (толькі для распрацоўшчыкаў)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Неапрацаваныя метаданыя: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Падрабязная інфармацыя пра мультымедыя"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Такія файлы адкрываюцца з дапамогай"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Гэты файл паходзіць з:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Не выбрана"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Невядома"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Памеры"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Мп"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Каардынаты"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Вышыня"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Апертура"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Хуткасць затвора"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Працягласць"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Знята"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Фокусная адлегласць"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> мм"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Эквівалент ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Выканаўца"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Кампазітар"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Альбом"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Месцазнаходжанне"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Тыпы плыні"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Памер файла RAW (у байтах)"</string>
+</resources>
diff --git a/res/values-be/mimes.xml b/res/values-be/mimes.xml
new file mode 100644
index 0000000..42495bb
--- /dev/null
+++ b/res/values-be/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Файл <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Файл"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Відарыс"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Відарыс <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аўдыя"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Аўдыя <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Відэа"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Відэа <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Архіў <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Праграма Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Просты тэкст"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Дакумент HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Дакумент PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Дакумент Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Прэзентацыя PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Электр. табліца Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Дакумент Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Электр. табліца Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Прэзентацыя Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Рысунак Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Табліца Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Форма Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Карта Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Сайт Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Папка"</string>
+</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 9b13fce..d059b4b 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Сціснуць"</string>
<string name="menu_extract" msgid="8171946945982532262">"Выняць у…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Перайменаваць"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Уласцівасці"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Атрымаць інфармацыю"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Праглядзець тут: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Новае акно"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Выразаць"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Перамясціць"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Адхіліць"</string>
<string name="button_retry" msgid="4011461781916631389">"Паўтарыць спробу"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Выдаліць"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Паказаць у Правадніку"</string>
<string name="not_sorted" msgid="7813496644889115530">"Не адсартаваны"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Назва"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Кароткае апісанне"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Тып"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Памер"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Зменены"</string>
- <string name="directory_children" msgid="8115290268549503262">"Колькасць дзяцей"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Колькасць элементаў"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Па ўзрастанні"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Па ўбыванні"</string>
<string name="drawer_open" msgid="8071673398187261741">"Паказаць каранёвыя папкі"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Немагчыма адкрыць файл"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Немагчыма адкрыць файлы ў архівах"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Немагчыма выдаліць некаторыя дакументы"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Не атрымалася загрузіць уласцівасці"</string>
<string name="share_via" msgid="8725082736005677161">"Абагуліць праз"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Капіраванне файлаў"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Ідзе сцісканне файлаў"</string>
diff --git a/res/values-bg/inspector_strings.xml b/res/values-bg/inspector_strings.xml
new file mode 100644
index 0000000..9e6b1e6
--- /dev/null
+++ b/res/values-bg/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Информация"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Информацията за файла не можа да се зареди"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Инф. за отстр. на грешки (само за програмисти)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Необработени метаданни: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Подробности за мултимедията"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Този тип файл се отваря с/ъс"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Този файл е предоставен от"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Не е избрано"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Неизвестно"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Размери"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> мегапиксела"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координати"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Надморска височина"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MODEL">%2$s</xliff:g> от <xliff:g id="MAKE">%1$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Бленда"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Скорост на затвора"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Продължителност"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Заснето на"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Дължина на фокуса"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> мм"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Еквивалент на ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO: <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Изпълнител"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Композитор"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Албум"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Местоположение"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Типове поточно предаване"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Необработен размер (байтове)"</string>
+</resources>
diff --git a/res/values-bg/mimes.xml b/res/values-bg/mimes.xml
new file mode 100644
index 0000000..e4633f5
--- /dev/null
+++ b/res/values-bg/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> файл"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Файл"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Изображение"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> изображение"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аудио"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> аудиофайл"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Видео"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> видеоклип"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> архив"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Приложение за Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Неформатиран текст"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML документ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF документ"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Документ в Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Презентация в PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Ел. таблица в Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Документ в Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Ел. таблица в Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Презентация в Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Чертеж в Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Таблица в Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Формуляр в Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Карта в Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Сайт в Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Папка"</string>
+</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index f1f9b4b..14bc483 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Компресиране"</string>
<string name="menu_extract" msgid="8171946945982532262">"Извличане в/ъв…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Преименуване"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Свойства"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Получаване на информация"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Преглед в/ъв <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Нов прозорец"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Изрязване"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Преместване"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Отхвърляне"</string>
<string name="button_retry" msgid="4011461781916631389">"Нов опит"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Изчистване"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Показване чрез доставчик"</string>
<string name="not_sorted" msgid="7813496644889115530">"Несортирани"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Име"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Обобщена информация"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Тип"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Размер"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Променено"</string>
- <string name="directory_children" msgid="8115290268549503262">"Брой деца"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Брой елементи"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Възходящ ред"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Низходящ ред"</string>
<string name="drawer_open" msgid="8071673398187261741">"Показване на основните елементи"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Файлът не може да се отвори"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Файловете в архиви не могат да се отварят"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Някои документи не могат да бъдат изтрити"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Свойствата не можаха да се заредят"</string>
<string name="share_via" msgid="8725082736005677161">"Споделяне чрез"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Копиране на файлове"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Файловете се компресират"</string>
diff --git a/res/values-bn/inspector_strings.xml b/res/values-bn/inspector_strings.xml
new file mode 100644
index 0000000..a9d1049
--- /dev/null
+++ b/res/values-bn/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"তথ্য"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ফাইলের তথ্য লোড করা যায়নি"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ত্রুটি সারানোর তথ্য (শুধুমাত্র ডেভেলপারের জন্য)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"RAW মেটাডেটা: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"মিডিয়ার বিশদ বিবরণ"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"এই ধরনের ফাইল এই অ্যাপ দিয়ে খোলা যায়"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"এই ফাইলের সরবরাহকারী"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"বেছে নেওয়া হয়নি"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"অজানা"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"দৈর্ঘ্য-প্রস্থ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"স্থানাঙ্ক"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"সমুদ্রপৃষ্ঠ থেকে উচ্চতা"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"ক্যামেরা"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"অ্যাপারচার"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"শাটার স্পিড"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"সময়কাল"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"তোলার তারিখ"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ফোকাল লেংথ"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ইকুইভ্যালেন্ট"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"শিল্পী"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"সুরকার"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"অ্যালবাম"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"লোকেশন"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"স্ট্রিমের ধরন"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"RAW এর সাইজ (বাইট)"</string>
+</resources>
diff --git a/res/values-bn/mimes.xml b/res/values-bn/mimes.xml
new file mode 100644
index 0000000..4cbc245
--- /dev/null
+++ b/res/values-bn/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ফাইল"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ফাইল"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"ছবি"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> ছবি"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"অডিও"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> অডিও"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ভিডিও"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> ভিডিও"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> আর্কাইভ"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android অ্যাপ্লিকেশান"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"সাধারণ টেক্সট"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML ডকুমেন্ট"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ডকুমেন্ট"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ডকুমেন্ট"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint উপস্থাপনা"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel স্প্রেডশিট"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google ডকুমেন্ট"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google স্প্রেডশিট"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google উপস্থাপনা"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google অঙ্কন"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google সারণী"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ফর্ম"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google ম্যাপ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google সাইট"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ফোল্ডার"</string>
+</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 9bc8df1..a804b73 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -23,33 +23,33 @@
<!-- no translation found for launcher_label (799410258349837668) -->
<skip />
<string name="title_open" msgid="3165686459158020921">"এখান থেকে খুলুন"</string>
- <string name="title_save" msgid="4384490653102710025">"এতে সংরক্ষণ করুন"</string>
+ <string name="title_save" msgid="4384490653102710025">"এতে সেভ করুন"</string>
<string name="menu_create_dir" msgid="2413624798689091042">"নতুন ফোল্ডার"</string>
<string name="menu_grid" msgid="1453636521731880680">"গ্রিড দৃশ্য"</string>
<string name="menu_list" msgid="6714267452146410402">"তালিকা দৃশ্য"</string>
- <string name="menu_search" msgid="1876699106790719849">"অনুসন্ধান করুন"</string>
+ <string name="menu_search" msgid="1876699106790719849">"খুঁজুন"</string>
<string name="menu_settings" msgid="6520844520117939047">"সঞ্চয়স্থানের সেটিংস"</string>
<string name="menu_open" msgid="9092138100049759315">"খুলুন"</string>
<string name="menu_open_with" msgid="5507647065467520229">"এর মাধ্যমে খুলুন"</string>
<string name="menu_open_in_new_window" msgid="6686563636123311276">"নতুন উইন্ডোতে খুলুন"</string>
- <string name="menu_save" msgid="5195367497138965168">"সংরক্ষণ করুন"</string>
+ <string name="menu_save" msgid="5195367497138965168">"সেভ করুন"</string>
<string name="menu_share" msgid="4307140947108068356">"শেয়ার করুন"</string>
<string name="menu_delete" msgid="1022254131543256626">"মুছুন"</string>
- <string name="menu_select_all" msgid="7600576812185570403">"সবগুলি নির্বাচন করুন"</string>
+ <string name="menu_select_all" msgid="7600576812185570403">"সবগুলি বেছে নিন"</string>
<string name="menu_copy" msgid="7404820171352314754">"এতে কপি করুন…"</string>
<string name="menu_move" msgid="2310760789561129882">"এতে সরান…"</string>
<string name="menu_compress" msgid="37539111904724188">"সঙ্কুচিত করুন"</string>
<string name="menu_extract" msgid="8171946945982532262">"এখানে রাখুন…"</string>
<string name="menu_rename" msgid="1883113442688817554">"পুনঃনামকরণ"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"বৈশিষ্ট্য"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"তথ্য পান"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> এ দেখুন"</string>
<string name="menu_new_window" msgid="2947837751796109126">"নতুন উইন্ডো"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"কাট করুন"</string>
<string name="menu_copy_to_clipboard" msgid="5064081159073330776">"কপি করুন"</string>
<string name="menu_paste_from_clipboard" msgid="360947260414135827">"পেস্ট করুন"</string>
<string name="menu_paste_into_folder" msgid="8000644546983240101">"ফোল্ডারে পেস্ট করুন"</string>
- <string name="menu_advanced_show" msgid="7558626506462906726">"অভ্যন্তরীণ সঞ্চয়স্থান দেখান"</string>
- <string name="menu_advanced_hide" msgid="6488381508009246334">"অভ্যন্তরীণ সঞ্চয়স্থান লুকান"</string>
+ <string name="menu_advanced_show" msgid="7558626506462906726">"ইন্টারনাল স্টোরেজ দেখান"</string>
+ <string name="menu_advanced_hide" msgid="6488381508009246334">"ইন্টারনাল স্টোরেজ লুকান"</string>
<string name="button_select" msgid="240863497069321364">"বেছে নিন"</string>
<string name="button_copy" msgid="8219059853840996027">"কপি করুন"</string>
<string name="button_compress" msgid="8951561310857223966">"সঙ্কুচিত করুন"</string>
@@ -57,32 +57,33 @@
<string name="button_move" msgid="8596460499325291272">"সরান"</string>
<string name="button_dismiss" msgid="7235249361023803349">"খারিজ করুন"</string>
<string name="button_retry" msgid="4011461781916631389">"আবার চেষ্টা করুন"</string>
+ <string name="button_clear" msgid="5412304437764369441">"সাফ করুন"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"প্রদানকারীতে দেখুন"</string>
<string name="not_sorted" msgid="7813496644889115530">"সাজানো নেই"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"নাম"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"সারাংশ"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ধরণ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"আকার"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"শেষ সংশোধিত"</string>
- <string name="directory_children" msgid="8115290268549503262">"শিশুদের সংখ্যা"</string>
+ <string name="directory_items" msgid="6645621978998614003">"আইটেমের সংখ্যা"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ঊর্ধ্বক্রম"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"নিম্নক্রম"</string>
<string name="drawer_open" msgid="8071673398187261741">"রুটগুলি দেখান"</string>
<string name="drawer_close" msgid="4263880768630848848">"রুটগুলি লুকান"</string>
<string name="save_error" msgid="8631128801982095782">"দস্তাবেজ সংরক্ষণ করা গেল না"</string>
<string name="create_error" msgid="3092144450044861994">"ফোল্ডার তৈরি করা গেল না"</string>
- <string name="query_error" msgid="6625421453613879336">"এই মুহূর্তে সামগ্রী লোড করা যাবে না"</string>
+ <string name="query_error" msgid="6625421453613879336">"এই মুহূর্তে কন্টেন্ট লোড করা যাবে না"</string>
<string name="root_recent" msgid="1080156975424341623">"সাম্প্রতিক"</string>
<string name="root_available_bytes" msgid="8269870862691408864">"<xliff:g id="SIZE">%1$s</xliff:g> খালি আছে"</string>
<string name="root_type_service" msgid="6521366147466512289">"সঞ্চয়স্থানের পরিষেবা"</string>
<string name="root_type_shortcut" msgid="6059343175525442279">"শর্টকাট"</string>
<string name="root_type_device" msgid="1713604128005476585">"ডিভাইস"</string>
- <string name="root_type_apps" msgid="8646073235029886342">"আরো অ্যাপ্স"</string>
+ <string name="root_type_apps" msgid="8646073235029886342">"আরও অ্যাপ্স"</string>
<string name="empty" msgid="5300254272613103004">"কোনো আইটেম নেই"</string>
<string name="no_results" msgid="2371026325236359209">"%1$s এ কোনো মিল নেই"</string>
<string name="toast_no_application" msgid="7555319548595113121">"ফাইল খোলা যাবে না"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"আর্কাইভের ফাইলগুলি খোলা যাচ্ছে না"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"কিছু দস্তাবেজ মোছা গেল না"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"বৈশিষ্ট্যগুলি লোড করা যায়নি"</string>
<string name="share_via" msgid="8725082736005677161">"এর মাধ্যমে শেয়ার করুন"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ফাইলগুলি কপি করা হচ্ছে"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ফাইলগুলি"</string>
@@ -189,19 +190,19 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মুছবেন?</item>
</plurals>
<plurals name="delete_folders_confirmation_message" formatted="false" msgid="1028946402799686388">
- <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফোল্ডার এবং সেগুলির সামগ্রী মুছবেন?</item>
- <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফোল্ডার এবং সেগুলির সামগ্রী মুছবেন?</item>
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফোল্ডার এবং সেগুলির কন্টেন্ট মুছবেন?</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফোল্ডার এবং সেগুলির কন্টেন্ট মুছবেন?</item>
</plurals>
<plurals name="delete_items_confirmation_message" formatted="false" msgid="7285090426511028179">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি আইটেম মুছবেন?</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি আইটেম মুছবেন?</item>
</plurals>
- <string name="images_shortcut_label" msgid="2545168016070493574">"চিত্রগুলি"</string>
- <string name="archive_loading_failed" msgid="7243436722828766996">"ব্রাউজ করার জন্য সংরক্ষণাগার খোলা গেল না৷ হয় ফাইলটি ক্ষতিগ্রস্ত বা কোনো অসমর্থিত বিন্যাসে রয়েছে৷"</string>
+ <string name="images_shortcut_label" msgid="2545168016070493574">"ছবিগুলি"</string>
+ <string name="archive_loading_failed" msgid="7243436722828766996">"ব্রাউজ করার জন্য আর্কাইভ খোলা গেল না৷ হয় ফাইলটি ক্ষতিগ্রস্ত বা কোনো অসমর্থিত বিন্যাসে রয়েছে৷"</string>
<string name="name_conflict" msgid="28407269328862986">"এই নামে আগেই আর একটি ফাইল আছে।"</string>
- <string name="authentication_required" msgid="8030880723643436099">"এই সংগ্রহটি দেখার জন্য <xliff:g id="NAME">%1$s</xliff:g> এ প্রবেশ করুন"</string>
- <string name="cant_display_content" msgid="8633226333229417237">"সামগ্রীগুলি প্রদর্শন করা যাচ্ছে না"</string>
- <string name="sign_in" msgid="6253762676723505592">"প্রবেশ করুন"</string>
+ <string name="authentication_required" msgid="8030880723643436099">"এই সংগ্রহটি দেখার জন্য <xliff:g id="NAME">%1$s</xliff:g> এ সাইন-ইন করুন"</string>
+ <string name="cant_display_content" msgid="8633226333229417237">"কন্টেন্ট প্রদর্শন করা যাচ্ছে না"</string>
+ <string name="sign_in" msgid="6253762676723505592">"সাইন-ইন করুন"</string>
<string name="new_archive_file_name" msgid="1604650338077249838">"সংরক্ষণ<xliff:g id="EXTENSION">%s</xliff:g>"</string>
<string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"<xliff:g id="NAME">%1$s</xliff:g> ওভাররাইট করবেন?"</string>
<string name="continue_in_background" msgid="1974214559047793331">"পটভূমিতে চালিয়ে যান"</string>
diff --git a/res/values-bs/inspector_strings.xml b/res/values-bs/inspector_strings.xml
new file mode 100644
index 0000000..503216b
--- /dev/null
+++ b/res/values-bs/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informacije"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Informacije o fajlu nisu učitane"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informacije o otklanjanju grešaka (samo dev)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw metapodaci: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalji o medijima"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ovu vrstu datoteka otvara aplikacija"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Fajl pruža"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nije odabrano"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Nepoznato"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimenzije"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Visina"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Blenda"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Brzina zatvarača"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Trajanje"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Vrijeme snimanja"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Žižna daljina"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Umjetnik"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Kompozitor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokacija"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Vrste prijenosa"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw veličina (bajta)"</string>
+</resources>
diff --git a/res/values-bs/mimes.xml b/res/values-bs/mimes.xml
new file mode 100644
index 0000000..ab0aecf
--- /dev/null
+++ b/res/values-bs/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> fajl"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fajl"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Slika"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> slika"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Zvuk"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Videozapis"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> videozapis"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> arhiva"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android aplikacija"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Obični tekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint prezentacija"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Tabela u Excelu"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google tabela"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google prezentacija"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google crtež"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google tabela"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google obrazac"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google Mapa"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google web lokacija"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index de60404..e15712c 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -33,15 +33,15 @@
<string name="menu_open_with" msgid="5507647065467520229">"Otvori koristeći"</string>
<string name="menu_open_in_new_window" msgid="6686563636123311276">"Otvori u novom prozoru"</string>
<string name="menu_save" msgid="5195367497138965168">"Sačuvaj"</string>
- <string name="menu_share" msgid="4307140947108068356">"Podijeli"</string>
+ <string name="menu_share" msgid="4307140947108068356">"Dijeli"</string>
<string name="menu_delete" msgid="1022254131543256626">"Izbriši"</string>
<string name="menu_select_all" msgid="7600576812185570403">"Odaberi sve"</string>
- <string name="menu_copy" msgid="7404820171352314754">"Kopiraj na…"</string>
+ <string name="menu_copy" msgid="7404820171352314754">"Kopiraj u…"</string>
<string name="menu_move" msgid="2310760789561129882">"Premjesti u…"</string>
<string name="menu_compress" msgid="37539111904724188">"Kompresiraj"</string>
<string name="menu_extract" msgid="8171946945982532262">"Izdvoji u…"</string>
- <string name="menu_rename" msgid="1883113442688817554">"Preimenuj"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Svojstva"</string>
+ <string name="menu_rename" msgid="1883113442688817554">"Promijeni naziv"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Prikaži informacije"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Prikaži u usluzi <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Novi prozor"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Izreži"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Premjesti"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Odbaci"</string>
<string name="button_retry" msgid="4011461781916631389">"Pokušajte ponovo"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Obriši"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Prikaži u pružaocu"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nije poredano"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Ime"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Sažetak"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Vrsta"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Veličina"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Izmijenjeno"</string>
- <string name="directory_children" msgid="8115290268549503262">"Broj djece"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Broj stavki"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Rastuće"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Opadajuće"</string>
<string name="drawer_open" msgid="8071673398187261741">"Prikaži korijenske fordere"</string>
@@ -82,8 +84,7 @@
<string name="toast_no_application" msgid="7555319548595113121">"Nije moguće otvoriti fajl"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Nije moguće otvoriti fajlove u arhivama"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nije moguće izbrisati neke dokumente"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Svojstva nisu učitana"</string>
- <string name="share_via" msgid="8725082736005677161">"Podijeli koristeći aplikaciju"</string>
+ <string name="share_via" msgid="8725082736005677161">"Dijeli koristeći aplikaciju"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopiraju se fajlovi"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Kompresovanje fajlova"</string>
<string name="extract_notification_title" msgid="5067393961754430469">"Izdvajanje fajlova"</string>
@@ -116,7 +117,7 @@
<item quantity="other">Briše se <xliff:g id="COUNT_1">%1$d</xliff:g> stavki.</item>
</plurals>
<string name="undo" msgid="2902438994196400565">"Opozovi radnju"</string>
- <string name="copy_preparing" msgid="5326063807006898223">"Priprema se kopiranje…"</string>
+ <string name="copy_preparing" msgid="5326063807006898223">"Priprema za kopiranje…"</string>
<string name="compress_preparing" msgid="6650018601382062672">"Priprema za kompresiranje…"</string>
<string name="extract_preparing" msgid="58266275455027829">"Priprema za izdvajanje…"</string>
<string name="move_preparing" msgid="8742573245485449429">"Priprema za premještanje…"</string>
@@ -181,7 +182,7 @@
</plurals>
<string name="file_operation_rejected" msgid="4301554203329008794">"Nije podržana operacija za fajl."</string>
<string name="file_operation_error" msgid="2234357335716533795">"Operacija za fajl nije uspjela."</string>
- <string name="rename_error" msgid="6700093173508118635">"Dokument nije preimenovan"</string>
+ <string name="rename_error" msgid="6700093173508118635">"Promjena naziva dokumenta nije uspjela"</string>
<string name="menu_eject_root" msgid="9215040039374893613">"Izbaci"</string>
<string name="notification_copy_files_converted_title" msgid="6916768494891833365">"Neki fajlovi su pretvoreni u drugi format"</string>
<string name="open_external_dialog_request" msgid="8173558471322861268">"Želite li aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> odobriti pristup direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> na pohrani <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
diff --git a/res/values-ca/inspector_strings.xml b/res/values-ca/inspector_strings.xml
new file mode 100644
index 0000000..329f950
--- /dev/null
+++ b/res/values-ca/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informació"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"No s\'ha pogut carregar la informació del fitxer"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informació de depuració (per a desenvolupadors)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadades sense processar: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Dades multimèdia"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Aquest tipus de fitxer s\'obre amb"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Aquest fitxer prové de:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"No s\'ha seleccionat"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Desconeguda"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>: <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Mpx"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordenades"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitud"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Càmera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Obertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocitat de l\'obturador"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Durada"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Data de la foto:"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Distància focal"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Equivalent d\'ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Àlbum"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Ubicació"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipus de fluxos"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Mida sense processar (bytes)"</string>
+</resources>
diff --git a/res/values-ca/mimes.xml b/res/values-ca/mimes.xml
new file mode 100644
index 0000000..ab35d69
--- /dev/null
+++ b/res/values-ca/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Fitxer <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fitxer"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imatge"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imatge <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Àudio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Àudio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vídeo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vídeo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arxiu <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicació per a Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Text sense format"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Document HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Document PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Document de Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Presentació de PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Full de càlcul d\'Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Document de Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Full de càlcul de Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Presentació de Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Dibuix de Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Taula de Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulari de Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa de Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Lloc web de Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Carpeta"</string>
+</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 4d2ffdc..97789d7 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimeix"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extreu a…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Canvia el nom"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propietats"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Obtén informació"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Mostra a <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Finestra nova"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Retalla"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mou"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ignora"</string>
<string name="button_retry" msgid="4011461781916631389">"Torna-ho a provar"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Esborra"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostra al proveïdor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sense ordenar"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nom"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Resum"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipus"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Mida"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modificat"</string>
- <string name="directory_children" msgid="8115290268549503262">"Nombre de nens"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Nombre d\'elements"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascendent"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descendent"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostra les arrels"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"No es pot obrir el fitxer"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"No es poden obrir els fitxers dels arxius"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"No es poden suprimir alguns documents"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"No s\'han pogut carregar les propietats"</string>
<string name="share_via" msgid="8725082736005677161">"Comparteix mitjançant"</string>
<string name="copy_notification_title" msgid="52256435625098456">"S\'estan copiant fitxers"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Comprimint els fitxers"</string>
diff --git a/res/values-cs/inspector_strings.xml b/res/values-cs/inspector_strings.xml
new file mode 100644
index 0000000..95705e1
--- /dev/null
+++ b/res/values-cs/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informace"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Informace o souboru nelze načíst"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informace o ladění (pouze vývojáři)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadata souboru RAW: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Podrobnosti o mediálním obsahu"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Tento typ souborů se otevírá pomocí aplikace"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Poskytovatel souboru:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nevybráno"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Neznámé"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Rozměry"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Mpx"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Souřadnice"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Výška"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Fotoaparát"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Clona"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Rychlost závěrky"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Doba trvání"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Pořízeno"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Ohnisková vzdálenost"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Ekvivalent ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Interpret"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Skladatel"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Místo"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Typy streamů"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Velikost souboru RAW (bajty)"</string>
+</resources>
diff --git a/res/values-cs/mimes.xml b/res/values-cs/mimes.xml
new file mode 100644
index 0000000..c92f8cc
--- /dev/null
+++ b/res/values-cs/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Soubor <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Soubor"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Obrázek"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Obrázek <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Zvuk"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Zvuk <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archiv <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplikace Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Prostý text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Dokument HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Dokument PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Dokument Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Prezentace PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Tabulka Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Dokument Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Tabulka Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Prezentace Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Nákres Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabulka Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulář Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Web Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Složka"</string>
+</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 701aab9..f768b2d 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Zkomprimovat"</string>
<string name="menu_extract" msgid="8171946945982532262">"Rozbalit do…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Přejmenovat"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Vlastnosti"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Zobrazit informace"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Zobrazit ve službě <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nové okno"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Vyjmout"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Přesunout"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Zavřít"</string>
<string name="button_retry" msgid="4011461781916631389">"Zkusit znovu"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Vymazat"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Zobrazit u poskytovatele"</string>
<string name="not_sorted" msgid="7813496644889115530">"Neřazeno"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Název"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Souhrn"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Typ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Velikost"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Změněno"</string>
- <string name="directory_children" msgid="8115290268549503262">"Počet dětí"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Počet položek"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Vzestupně"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Sestupně"</string>
<string name="drawer_open" msgid="8071673398187261741">"Zobrazit kořeny"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Soubor nelze otevřít"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Soubory v archivu nelze otevírat"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Některé dokumenty nelze smazat"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Vlastnosti nelze načíst"</string>
<string name="share_via" msgid="8725082736005677161">"Sdílet pomocí"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopírování souborů"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Komprimace souborů"</string>
diff --git a/res/values-da/inspector_strings.xml b/res/values-da/inspector_strings.xml
new file mode 100644
index 0000000..582e9d1
--- /dev/null
+++ b/res/values-da/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Oplysninger"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Filoplysningerne kunne ikke indlæses"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Oplysninger om fejlretning (kun på enheden)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"RAW-metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Medieoplysninger"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Denne filtype åbnes med"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Denne fil leveres af"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Ikke valgt"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Ukendt"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Mål"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinater"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Højde"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Blænde"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Lukkertid"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Varighed"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Taget den"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Fokuslængde"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Tilsvarende ISO-hastighed"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Musiker"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Komponist"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Placering"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Streamingtyper"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"RAW-størrelse (i bytes)"</string>
+</resources>
diff --git a/res/values-da/mimes.xml b/res/values-da/mimes.xml
new file mode 100644
index 0000000..f6be5b7
--- /dev/null
+++ b/res/values-da/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-fil"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fil"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Billede"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-billede"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Lyd"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-lyd"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-arkiv"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-applikation"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Almindelig tekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-præsentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-regneark"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-regneark"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-præsentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-tegning"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-tabel"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-formular"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-kort"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-website"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mappe"</string>
+</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index fe3dae3..20da773 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Komprimer"</string>
<string name="menu_extract" msgid="8171946945982532262">"Pak ud i…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Omdøb"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Egenskaber"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Få oplysninger"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Se i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nyt vindue"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Klip"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Flyt"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Afvis"</string>
<string name="button_retry" msgid="4011461781916631389">"Prøv igen"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Ryd"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Vis i udbyders tjeneste"</string>
<string name="not_sorted" msgid="7813496644889115530">"Ikke sorteret"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Navn"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Oversigt"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Størrelse"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Ændret"</string>
- <string name="directory_children" msgid="8115290268549503262">"Antal børn"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Antal elementer"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Stigende rækkefølge"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Faldende rækkefølge"</string>
<string name="drawer_open" msgid="8071673398187261741">"Vis rødder"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Filen kan ikke åbnes"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Filer i arkiver kan ikke åbnes"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nogle dokumenter kan ikke slettes"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Ejendommene kunne ikke indlæses"</string>
<string name="share_via" msgid="8725082736005677161">"Del via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopierer filer"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Komprimerer filer"</string>
@@ -175,8 +176,8 @@
<string name="allow" msgid="1275746941353040309">"Tillad"</string>
<string name="deny" msgid="5127201668078153379">"Afvis"</string>
<plurals name="elements_selected" formatted="false" msgid="4448165978637163692">
- <item quantity="one">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
- <item quantity="other">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> er markeret</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> er markeret</item>
</plurals>
<plurals name="elements_dragged" formatted="false" msgid="5932571296037626279">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> element</item>
diff --git a/res/values-de/inspector_strings.xml b/res/values-de/inspector_strings.xml
new file mode 100644
index 0000000..9a8356d
--- /dev/null
+++ b/res/values-de/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informationen"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Dateiinformationen konnten nicht geladen werden"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Infos zur Fehlersuche (nur für Entwickler)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Unkomprimierte Metadaten: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Mediendetails"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Dieser Dateityp wird mit der folgenden App geöffnet:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Diese Datei wird bereitgestellt von"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nicht ausgewählt"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Unbekannt"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Abmessungen"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinaten"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Höhe"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Blende"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Belichtungszeit"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Dauer"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Aufgenommen am"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Brennweite"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-Äquivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Interpret"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Komponist"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Standort"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Streamingtypen"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Unkomprimierte Größe (Byte)"</string>
+</resources>
diff --git a/res/values-de/mimes.xml b/res/values-de/mimes.xml
new file mode 100644
index 0000000..6772c95
--- /dev/null
+++ b/res/values-de/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-Datei"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Datei"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Bild"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-Bild"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-Audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-Video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-Archiv"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-App"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Nur Text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-Dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-Dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-Dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-Präsentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-Tabelle"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-Dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-Tabelle"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-Präsentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-Zeichnung"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-Tabelle"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-Formular"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-Karte"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-Website"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Ordner"</string>
+</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index c29e631..703b791 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Komprimieren"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extrahieren nach…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Umbenennen"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Eigenschaften"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Weitere Informationen"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"In <xliff:g id="SOURCE">%1$s</xliff:g> ansehen"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Neues Fenster"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Ausschneiden"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Verschieben"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Schließen"</string>
<string name="button_retry" msgid="4011461781916631389">"Wiederholen"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Löschen"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"In App des Anbieters anzeigen"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nicht sortiert"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Name"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Zusammenfassung"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Dateityp"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Größe"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Geändert"</string>
- <string name="directory_children" msgid="8115290268549503262">"Anzahl der Kinder"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Anzahl der Elemente"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Aufsteigend"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Absteigend"</string>
<string name="drawer_open" msgid="8071673398187261741">"Root-Verzeichnis anzeigen"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Datei kann nicht geöffnet werden"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Dateien in Archiven können nicht geöffnet werden"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Einige Dokumente konnten nicht gelöscht werden"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Eigenschaften konnten nicht geladen werden"</string>
<string name="share_via" msgid="8725082736005677161">"Teilen über"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Dateien werden kopiert"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Dateien werden komprimiert"</string>
diff --git a/res/values-el/inspector_strings.xml b/res/values-el/inspector_strings.xml
new file mode 100644
index 0000000..7731009
--- /dev/null
+++ b/res/values-el/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Πληροφορίες"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Δεν ήταν δυνατή η φόρτωση των πληροφοριών αρχείου"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Πληροφορίες εντοπισμού σφαλμάτων (μόνο προγρ.)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Μη επεξεργασμένα μεταδεδομένα: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Λεπτομέρειες μέσων"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Αυτός ο τύπος αρχείου ανοίγει με"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Αυτό το αρχείο παρέχεται από"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Δεν έχει επιλεγεί"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Άγνωστη"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Διαστάσεις"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Συντεταγμένες"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Υψόμετρο"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Κάμερα"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Διάφραγμα"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Ταχύτητα κλείστρου"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Διάρκεια"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Λήψη στις"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Εστιακό μήκος"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> χλστ."</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Ισοδύναμο ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Καλλιτέχνης"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Συνθέτης"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Άλμπουμ"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Τοποθεσία"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Τύποι ροής"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Μη επεξεργασμένο μέγεθος (byte)"</string>
+</resources>
diff --git a/res/values-el/mimes.xml b/res/values-el/mimes.xml
new file mode 100644
index 0000000..b94d035
--- /dev/null
+++ b/res/values-el/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Αρχείο <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Αρχείο"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Εικόνα"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Εικόνα <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Ήχος"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Ήχος <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Βίντεο"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Βίντεο <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Αρχείο <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Εφαρμογή Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Απλό κείμενο"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Έγγραφο HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Έγγραφο PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Έγγραφο Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Παρουσίαση PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Υπολογιστικό φύλλο Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Έγγραφο Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Υπολογιστικό φύλλο Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Παρουσίαση Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Σχέδιο Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Πίνακας Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Φόρμα Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Χάρτης Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Ιστότοπος Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Φάκελος"</string>
+</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 5a51875..003ef4c 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Συμπίεση"</string>
<string name="menu_extract" msgid="8171946945982532262">"Εξαγωγή σε…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Μετονομασία"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Ιδιότητες"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Λήψη πληροφοριών"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Προβολή σε <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Νέο παράθυρο"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Αποκοπή"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Μετακίνηση"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Παράβλεψη"</string>
<string name="button_retry" msgid="4011461781916631389">"Δοκιμάστε ξανά"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Διαγραφή"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Εμφάνιση στον πάροχο"</string>
<string name="not_sorted" msgid="7813496644889115530">"Χωρίς ταξινόμηση"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Όνομα"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Σύνοψη"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Τύπος"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Μέγεθος"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Τροποποιημένα"</string>
- <string name="directory_children" msgid="8115290268549503262">"Αριθμός παιδιών"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Αριθμός στοιχείων"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Αύξουσα"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Φθίνουσα"</string>
<string name="drawer_open" msgid="8071673398187261741">"Εμφάνιση ριζών"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Δεν είναι δυνατό το άνοιγμα του αρχείου"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Αδύνατο άνοιγμα αρχείων σε αρχειοθήκες"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Δεν είναι δυνατή η διαγραφή ορισμένων εγγράφων"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Η φόρτωση των ιδιοτήτων δεν ήταν δυνατή"</string>
<string name="share_via" msgid="8725082736005677161">"Κοινοποίηση μέσω"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Αντιγραφή αρχείων"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Συμπίεση αρχείων"</string>
diff --git a/res/values-en-rAU/inspector_strings.xml b/res/values-en-rAU/inspector_strings.xml
new file mode 100644
index 0000000..89d9e75
--- /dev/null
+++ b/res/values-en-rAU/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Info"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"File info could not be loaded"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Debug info (dev only)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Media details"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"This kind of file opens with"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"This file is supplied by"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Not selected"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Unknown"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordinates"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aperture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Shutter speed"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duration"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Taken on"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Focal length"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO equivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Composer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Location"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stream types"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw size (bytes)"</string>
+</resources>
diff --git a/res/values-en-rAU/mimes.xml b/res/values-en-rAU/mimes.xml
new file mode 100644
index 0000000..7b10dd4
--- /dev/null
+++ b/res/values-en-rAU/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> file"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Image"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> image"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> archive"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android application"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Plain text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML document"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF document"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word document"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint presentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel spreadsheet"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google document"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google spreadsheet"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google presentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google drawing"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google table"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google form"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google map"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 6c5d10f..8ffcdbc 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Compress"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extract to…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Rename"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Properties"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Get info"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"View in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"New window"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cut"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Move"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Dismiss"</string>
<string name="button_retry" msgid="4011461781916631389">"Try again"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Clear"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Show in provider"</string>
<string name="not_sorted" msgid="7813496644889115530">"Not sorted"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Name"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Summary"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type:"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Size"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modified"</string>
- <string name="directory_children" msgid="8115290268549503262">"Number of Children"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Number of items"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascending"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descending"</string>
<string name="drawer_open" msgid="8071673398187261741">"Show roots"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Can’t open file"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Cannot open files in archives"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Unable to delete some documents"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Properties could not be loaded"</string>
<string name="share_via" msgid="8725082736005677161">"Share via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copying files"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compressing files"</string>
diff --git a/res/values-en-rCA/inspector_strings.xml b/res/values-en-rCA/inspector_strings.xml
new file mode 100644
index 0000000..89d9e75
--- /dev/null
+++ b/res/values-en-rCA/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Info"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"File info could not be loaded"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Debug info (dev only)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Media details"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"This kind of file opens with"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"This file is supplied by"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Not selected"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Unknown"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordinates"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aperture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Shutter speed"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duration"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Taken on"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Focal length"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO equivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Composer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Location"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stream types"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw size (bytes)"</string>
+</resources>
diff --git a/res/values-en-rCA/mimes.xml b/res/values-en-rCA/mimes.xml
new file mode 100644
index 0000000..7b10dd4
--- /dev/null
+++ b/res/values-en-rCA/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> file"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Image"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> image"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> archive"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android application"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Plain text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML document"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF document"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word document"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint presentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel spreadsheet"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google document"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google spreadsheet"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google presentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google drawing"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google table"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google form"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google map"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..8ffcdbc
--- /dev/null
+++ b/res/values-en-rCA/strings.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="files_label" msgid="771781190045103748">"Files"</string>
+ <string name="downloads_label" msgid="5462789470049501103">"Downloads"</string>
+ <!-- no translation found for app_label (8089292432455111409) -->
+ <skip />
+ <!-- no translation found for launcher_label (799410258349837668) -->
+ <skip />
+ <string name="title_open" msgid="3165686459158020921">"Open from"</string>
+ <string name="title_save" msgid="4384490653102710025">"Save to"</string>
+ <string name="menu_create_dir" msgid="2413624798689091042">"New folder"</string>
+ <string name="menu_grid" msgid="1453636521731880680">"Grid view"</string>
+ <string name="menu_list" msgid="6714267452146410402">"List View"</string>
+ <string name="menu_search" msgid="1876699106790719849">"Search"</string>
+ <string name="menu_settings" msgid="6520844520117939047">"Storage settings"</string>
+ <string name="menu_open" msgid="9092138100049759315">"Open"</string>
+ <string name="menu_open_with" msgid="5507647065467520229">"Open with"</string>
+ <string name="menu_open_in_new_window" msgid="6686563636123311276">"Open in new window"</string>
+ <string name="menu_save" msgid="5195367497138965168">"Save"</string>
+ <string name="menu_share" msgid="4307140947108068356">"Shared"</string>
+ <string name="menu_delete" msgid="1022254131543256626">"Delete"</string>
+ <string name="menu_select_all" msgid="7600576812185570403">"Select all"</string>
+ <string name="menu_copy" msgid="7404820171352314754">"Copy to…"</string>
+ <string name="menu_move" msgid="2310760789561129882">"Move to…"</string>
+ <string name="menu_compress" msgid="37539111904724188">"Compress"</string>
+ <string name="menu_extract" msgid="8171946945982532262">"Extract to…"</string>
+ <string name="menu_rename" msgid="1883113442688817554">"Rename"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Get info"</string>
+ <string name="menu_view_in_owner" msgid="7228948660557554770">"View in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <string name="menu_new_window" msgid="2947837751796109126">"New window"</string>
+ <string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cut"</string>
+ <string name="menu_copy_to_clipboard" msgid="5064081159073330776">"Copy"</string>
+ <string name="menu_paste_from_clipboard" msgid="360947260414135827">"Paste"</string>
+ <string name="menu_paste_into_folder" msgid="8000644546983240101">"Paste into folder"</string>
+ <string name="menu_advanced_show" msgid="7558626506462906726">"Show internal storage"</string>
+ <string name="menu_advanced_hide" msgid="6488381508009246334">"Hide internal storage"</string>
+ <string name="button_select" msgid="240863497069321364">"Select"</string>
+ <string name="button_copy" msgid="8219059853840996027">"Copy"</string>
+ <string name="button_compress" msgid="8951561310857223966">"Compress"</string>
+ <string name="button_extract" msgid="1038674453689912247">"Extract"</string>
+ <string name="button_move" msgid="8596460499325291272">"Move"</string>
+ <string name="button_dismiss" msgid="7235249361023803349">"Dismiss"</string>
+ <string name="button_retry" msgid="4011461781916631389">"Try again"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Clear"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Show in provider"</string>
+ <string name="not_sorted" msgid="7813496644889115530">"Not sorted"</string>
+ <string name="sort_dimension_name" msgid="6325591541414177579">"Name"</string>
+ <string name="sort_dimension_summary" msgid="7724534446881397860">"Summary"</string>
+ <string name="sort_dimension_file_type" msgid="5779709622922085381">"Type:"</string>
+ <string name="sort_dimension_size" msgid="2190547351159472884">"Size"</string>
+ <string name="sort_dimension_date" msgid="4231005651895254033">"Modified"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Number of items"</string>
+ <string name="sort_direction_ascending" msgid="5882787683763248102">"Ascending"</string>
+ <string name="sort_direction_descending" msgid="1729187589765894076">"Descending"</string>
+ <string name="drawer_open" msgid="8071673398187261741">"Show roots"</string>
+ <string name="drawer_close" msgid="4263880768630848848">"Hide roots"</string>
+ <string name="save_error" msgid="8631128801982095782">"Failed to save document"</string>
+ <string name="create_error" msgid="3092144450044861994">"Failed to create folder"</string>
+ <string name="query_error" msgid="6625421453613879336">"Can’t load content at the moment"</string>
+ <string name="root_recent" msgid="1080156975424341623">"Recent"</string>
+ <string name="root_available_bytes" msgid="8269870862691408864">"<xliff:g id="SIZE">%1$s</xliff:g> free"</string>
+ <string name="root_type_service" msgid="6521366147466512289">"Storage services"</string>
+ <string name="root_type_shortcut" msgid="6059343175525442279">"Shortcuts"</string>
+ <string name="root_type_device" msgid="1713604128005476585">"Devices"</string>
+ <string name="root_type_apps" msgid="8646073235029886342">"More apps"</string>
+ <string name="empty" msgid="5300254272613103004">"No items"</string>
+ <string name="no_results" msgid="2371026325236359209">"No matches in %1$s"</string>
+ <string name="toast_no_application" msgid="7555319548595113121">"Can’t open file"</string>
+ <string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Cannot open files in archives"</string>
+ <string name="toast_failed_delete" msgid="3453846588205817591">"Unable to delete some documents"</string>
+ <string name="share_via" msgid="8725082736005677161">"Share via"</string>
+ <string name="copy_notification_title" msgid="52256435625098456">"Copying files"</string>
+ <string name="compress_notification_title" msgid="6830195148113751021">"Compressing files"</string>
+ <string name="extract_notification_title" msgid="5067393961754430469">"Extracting files"</string>
+ <string name="move_notification_title" msgid="3173424987049347605">"Moving files"</string>
+ <string name="delete_notification_title" msgid="2512757431856830792">"Deleting files"</string>
+ <string name="copy_remaining" msgid="5390517377265177727">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
+ <plurals name="copy_begin" formatted="false" msgid="151184708996738192">
+ <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
+ <item quantity="one">Copying <xliff:g id="COUNT_0">%1$d</xliff:g> item.</item>
+ </plurals>
+ <plurals name="compress_begin" formatted="false" msgid="3534158317098678895">
+ <item quantity="other">Compressing <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
+ <item quantity="one">Compressing <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+ </plurals>
+ <plurals name="extract_begin" formatted="false" msgid="1006380679562903749">
+ <item quantity="other">Extracting <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
+ <item quantity="one">Extracting <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+ </plurals>
+ <plurals name="move_begin" formatted="false" msgid="1464229874265756956">
+ <item quantity="other">Moving <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
+ <item quantity="one">Moving <xliff:g id="COUNT_0">%1$d</xliff:g> item.</item>
+ </plurals>
+ <plurals name="deleting" formatted="false" msgid="1729138001178158901">
+ <item quantity="other">Deleting <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
+ <item quantity="one">Deleting <xliff:g id="COUNT_0">%1$d</xliff:g> item.</item>
+ </plurals>
+ <string name="undo" msgid="2902438994196400565">"Undo"</string>
+ <string name="copy_preparing" msgid="5326063807006898223">"Preparing for copy…"</string>
+ <string name="compress_preparing" msgid="6650018601382062672">"Preparing for compress…"</string>
+ <string name="extract_preparing" msgid="58266275455027829">"Preparing for extract…"</string>
+ <string name="move_preparing" msgid="8742573245485449429">"Preparing for move…"</string>
+ <string name="delete_preparing" msgid="6513863752916028147">"Preparing to delete…"</string>
+ <string name="delete_progress" msgid="2627631054702306423">"<xliff:g id="COUNT_0">%1$d</xliff:g> / <xliff:g id="TOTALCOUNT">%2$d</xliff:g>"</string>
+ <plurals name="copy_error_notification_title" formatted="false" msgid="3188432450429390963">
+ <item quantity="other">Couldn’t copy <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one">Couldn’t copy <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <plurals name="compress_error_notification_title" formatted="false" msgid="3043630066678213644">
+ <item quantity="other">Couldn’t compress <xliff:g id="COUNT_1">%1$d</xliff:g> files</item>
+ <item quantity="one">Couldn’t compress <xliff:g id="COUNT_0">%1$d</xliff:g> file</item>
+ </plurals>
+ <plurals name="move_error_notification_title" formatted="false" msgid="2185736082411854754">
+ <item quantity="other">Couldn’t move <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one">Couldn’t move <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <plurals name="delete_error_notification_title" formatted="false" msgid="7568122018481625267">
+ <item quantity="other">Couldn’t delete <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one">Couldn’t delete <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <string name="notification_touch_for_details" msgid="2385563502445129570">"Tap to view details"</string>
+ <string name="close" msgid="905969391788869975">"Close"</string>
+ <plurals name="copy_failure_alert_content" formatted="false" msgid="5570549471912990536">
+ <item quantity="other">These files weren’t copied: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t copied: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="compress_failure_alert_content" formatted="false" msgid="5760632881868842400">
+ <item quantity="other">These files weren’t compressed: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t compressed: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="extract_failure_alert_content" formatted="false" msgid="7572748127571720803">
+ <item quantity="other">These files weren’t extracted: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t extracted: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="move_failure_alert_content" formatted="false" msgid="2747390342670799196">
+ <item quantity="other">These files weren’t moved: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t moved: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="delete_failure_alert_content" formatted="false" msgid="6122372614839711711">
+ <item quantity="other">These files weren’t deleted: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t deleted: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="copy_converted_warning_content" formatted="false" msgid="7433742181712126588">
+ <item quantity="other">These files were converted to another format: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file was converted to another format: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="clipboard_files_clipped" formatted="false" msgid="4847061634862926902">
+ <item quantity="other">Copied <xliff:g id="COUNT_1">%1$d</xliff:g> items to clipboard.</item>
+ <item quantity="one">Copied <xliff:g id="COUNT_0">%1$d</xliff:g> item to clipboard.</item>
+ </plurals>
+ <string name="file_operation_rejected" msgid="4301554203329008794">"File operation is not supported."</string>
+ <string name="file_operation_error" msgid="2234357335716533795">"File operation failed."</string>
+ <string name="rename_error" msgid="6700093173508118635">"Failed to rename document"</string>
+ <string name="menu_eject_root" msgid="9215040039374893613">"Eject"</string>
+ <string name="notification_copy_files_converted_title" msgid="6916768494891833365">"Some files were converted"</string>
+ <string name="open_external_dialog_request" msgid="8173558471322861268">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
+ <string name="open_external_dialog_root_request" msgid="6776729293982633">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
+ <string name="never_ask_again" msgid="525908236522201138">"Don\'t ask again"</string>
+ <string name="allow" msgid="1275746941353040309">"Allow"</string>
+ <string name="deny" msgid="5127201668078153379">"Deny"</string>
+ <plurals name="elements_selected" formatted="false" msgid="4448165978637163692">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
+ </plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="5932571296037626279">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <string name="delete_filename_confirmation_message" msgid="8338069763240613258">"Delete \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="9084085260877704140">"Delete folder \"<xliff:g id="NAME">%1$s</xliff:g>\" and its contents?"</string>
+ <plurals name="delete_files_confirmation_message" formatted="false" msgid="4866664063250034142">
+ <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+ <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
+ <plurals name="delete_folders_confirmation_message" formatted="false" msgid="1028946402799686388">
+ <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> folders and their contents?</item>
+ <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> folder and its contents?</item>
+ </plurals>
+ <plurals name="delete_items_confirmation_message" formatted="false" msgid="7285090426511028179">
+ <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> items?</item>
+ <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> item?</item>
+ </plurals>
+ <string name="images_shortcut_label" msgid="2545168016070493574">"Images"</string>
+ <string name="archive_loading_failed" msgid="7243436722828766996">"Unable to open archive for browsing. File is either corrupt or an unsupported format."</string>
+ <string name="name_conflict" msgid="28407269328862986">"A file with this name already exists."</string>
+ <string name="authentication_required" msgid="8030880723643436099">"To view this directory, sign in to <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="cant_display_content" msgid="8633226333229417237">"Can’t display contents"</string>
+ <string name="sign_in" msgid="6253762676723505592">"Sign in"</string>
+ <string name="new_archive_file_name" msgid="1604650338077249838">"archive<xliff:g id="EXTENSION">%s</xliff:g>"</string>
+ <string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"Overwrite <xliff:g id="NAME">%1$s</xliff:g>?"</string>
+ <string name="continue_in_background" msgid="1974214559047793331">"Continue in background"</string>
+</resources>
diff --git a/res/values-en-rGB/inspector_strings.xml b/res/values-en-rGB/inspector_strings.xml
new file mode 100644
index 0000000..89d9e75
--- /dev/null
+++ b/res/values-en-rGB/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Info"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"File info could not be loaded"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Debug info (dev only)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Media details"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"This kind of file opens with"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"This file is supplied by"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Not selected"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Unknown"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordinates"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aperture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Shutter speed"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duration"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Taken on"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Focal length"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO equivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Composer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Location"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stream types"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw size (bytes)"</string>
+</resources>
diff --git a/res/values-en-rGB/mimes.xml b/res/values-en-rGB/mimes.xml
new file mode 100644
index 0000000..7b10dd4
--- /dev/null
+++ b/res/values-en-rGB/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> file"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Image"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> image"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> archive"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android application"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Plain text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML document"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF document"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word document"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint presentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel spreadsheet"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google document"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google spreadsheet"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google presentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google drawing"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google table"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google form"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google map"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 6c5d10f..8ffcdbc 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Compress"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extract to…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Rename"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Properties"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Get info"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"View in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"New window"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cut"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Move"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Dismiss"</string>
<string name="button_retry" msgid="4011461781916631389">"Try again"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Clear"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Show in provider"</string>
<string name="not_sorted" msgid="7813496644889115530">"Not sorted"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Name"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Summary"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type:"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Size"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modified"</string>
- <string name="directory_children" msgid="8115290268549503262">"Number of Children"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Number of items"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascending"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descending"</string>
<string name="drawer_open" msgid="8071673398187261741">"Show roots"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Can’t open file"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Cannot open files in archives"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Unable to delete some documents"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Properties could not be loaded"</string>
<string name="share_via" msgid="8725082736005677161">"Share via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copying files"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compressing files"</string>
diff --git a/res/values-en-rIN/inspector_strings.xml b/res/values-en-rIN/inspector_strings.xml
new file mode 100644
index 0000000..89d9e75
--- /dev/null
+++ b/res/values-en-rIN/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Info"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"File info could not be loaded"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Debug info (dev only)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Media details"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"This kind of file opens with"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"This file is supplied by"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Not selected"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Unknown"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordinates"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aperture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Shutter speed"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duration"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Taken on"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Focal length"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO equivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Composer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Location"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stream types"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw size (bytes)"</string>
+</resources>
diff --git a/res/values-en-rIN/mimes.xml b/res/values-en-rIN/mimes.xml
new file mode 100644
index 0000000..7b10dd4
--- /dev/null
+++ b/res/values-en-rIN/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> file"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Image"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> image"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> archive"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android application"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Plain text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML document"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF document"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word document"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint presentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel spreadsheet"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google document"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google spreadsheet"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google presentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google drawing"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google table"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google form"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google map"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 6c5d10f..8ffcdbc 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Compress"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extract to…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Rename"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Properties"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Get info"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"View in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"New window"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cut"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Move"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Dismiss"</string>
<string name="button_retry" msgid="4011461781916631389">"Try again"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Clear"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Show in provider"</string>
<string name="not_sorted" msgid="7813496644889115530">"Not sorted"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Name"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Summary"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type:"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Size"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modified"</string>
- <string name="directory_children" msgid="8115290268549503262">"Number of Children"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Number of items"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascending"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descending"</string>
<string name="drawer_open" msgid="8071673398187261741">"Show roots"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Can’t open file"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Cannot open files in archives"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Unable to delete some documents"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Properties could not be loaded"</string>
<string name="share_via" msgid="8725082736005677161">"Share via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copying files"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compressing files"</string>
diff --git a/res/values-en-rXC/inspector_strings.xml b/res/values-en-rXC/inspector_strings.xml
new file mode 100644
index 0000000..ace8d48
--- /dev/null
+++ b/res/values-en-rXC/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Info"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"File info could not be loaded"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Debug info (dev only)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Media details"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"This kind of file opens with"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"This file is supplied by"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Not selected"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Unknown"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordinates"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aperture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Shutter speed"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duration"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Taken on"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Focal length"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO equivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Composer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Location"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stream types"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw size (bytes)"</string>
+</resources>
diff --git a/res/values-en-rXC/mimes.xml b/res/values-en-rXC/mimes.xml
new file mode 100644
index 0000000..43489a9
--- /dev/null
+++ b/res/values-en-rXC/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> file"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Image"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> image"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> archive"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android application"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Plain text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML document"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF document"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word document"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint presentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel spreadsheet"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google document"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google spreadsheet"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google presentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google drawing"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google table"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google form"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google map"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..9e727f9
--- /dev/null
+++ b/res/values-en-rXC/strings.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="files_label" msgid="771781190045103748">"Files"</string>
+ <string name="downloads_label" msgid="5462789470049501103">"Downloads"</string>
+ <!-- no translation found for app_label (8089292432455111409) -->
+ <skip />
+ <!-- no translation found for launcher_label (799410258349837668) -->
+ <skip />
+ <string name="title_open" msgid="3165686459158020921">"Open from"</string>
+ <string name="title_save" msgid="4384490653102710025">"Save to"</string>
+ <string name="menu_create_dir" msgid="2413624798689091042">"New folder"</string>
+ <string name="menu_grid" msgid="1453636521731880680">"Grid view"</string>
+ <string name="menu_list" msgid="6714267452146410402">"List view"</string>
+ <string name="menu_search" msgid="1876699106790719849">"Search"</string>
+ <string name="menu_settings" msgid="6520844520117939047">"Storage settings"</string>
+ <string name="menu_open" msgid="9092138100049759315">"Open"</string>
+ <string name="menu_open_with" msgid="5507647065467520229">"Open with"</string>
+ <string name="menu_open_in_new_window" msgid="6686563636123311276">"Open in new window"</string>
+ <string name="menu_save" msgid="5195367497138965168">"Save"</string>
+ <string name="menu_share" msgid="4307140947108068356">"Share"</string>
+ <string name="menu_delete" msgid="1022254131543256626">"Delete"</string>
+ <string name="menu_select_all" msgid="7600576812185570403">"Select all"</string>
+ <string name="menu_copy" msgid="7404820171352314754">"Copy to…"</string>
+ <string name="menu_move" msgid="2310760789561129882">"Move to…"</string>
+ <string name="menu_compress" msgid="37539111904724188">"Compress"</string>
+ <string name="menu_extract" msgid="8171946945982532262">"Extract to…"</string>
+ <string name="menu_rename" msgid="1883113442688817554">"Rename"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Get info"</string>
+ <string name="menu_view_in_owner" msgid="7228948660557554770">"View in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <string name="menu_new_window" msgid="2947837751796109126">"New window"</string>
+ <string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cut"</string>
+ <string name="menu_copy_to_clipboard" msgid="5064081159073330776">"Copy"</string>
+ <string name="menu_paste_from_clipboard" msgid="360947260414135827">"Paste"</string>
+ <string name="menu_paste_into_folder" msgid="8000644546983240101">"Paste into folder"</string>
+ <string name="menu_advanced_show" msgid="7558626506462906726">"Show internal storage"</string>
+ <string name="menu_advanced_hide" msgid="6488381508009246334">"Hide internal storage"</string>
+ <string name="button_select" msgid="240863497069321364">"Select"</string>
+ <string name="button_copy" msgid="8219059853840996027">"Copy"</string>
+ <string name="button_compress" msgid="8951561310857223966">"Compress"</string>
+ <string name="button_extract" msgid="1038674453689912247">"Extract"</string>
+ <string name="button_move" msgid="8596460499325291272">"Move"</string>
+ <string name="button_dismiss" msgid="7235249361023803349">"Dismiss"</string>
+ <string name="button_retry" msgid="4011461781916631389">"Try Again"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Clear"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Show in provider"</string>
+ <string name="not_sorted" msgid="7813496644889115530">"Not sorted"</string>
+ <string name="sort_dimension_name" msgid="6325591541414177579">"Name"</string>
+ <string name="sort_dimension_summary" msgid="7724534446881397860">"Summary"</string>
+ <string name="sort_dimension_file_type" msgid="5779709622922085381">"Type"</string>
+ <string name="sort_dimension_size" msgid="2190547351159472884">"Size"</string>
+ <string name="sort_dimension_date" msgid="4231005651895254033">"Modified"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Number of items"</string>
+ <string name="sort_direction_ascending" msgid="5882787683763248102">"Ascending"</string>
+ <string name="sort_direction_descending" msgid="1729187589765894076">"Descending"</string>
+ <string name="drawer_open" msgid="8071673398187261741">"Show roots"</string>
+ <string name="drawer_close" msgid="4263880768630848848">"Hide roots"</string>
+ <string name="save_error" msgid="8631128801982095782">"Failed to save document"</string>
+ <string name="create_error" msgid="3092144450044861994">"Failed to create folder"</string>
+ <string name="query_error" msgid="6625421453613879336">"Can’t load content at the moment"</string>
+ <string name="root_recent" msgid="1080156975424341623">"Recent"</string>
+ <string name="root_available_bytes" msgid="8269870862691408864">"<xliff:g id="SIZE">%1$s</xliff:g> free"</string>
+ <string name="root_type_service" msgid="6521366147466512289">"Storage services"</string>
+ <string name="root_type_shortcut" msgid="6059343175525442279">"Shortcuts"</string>
+ <string name="root_type_device" msgid="1713604128005476585">"Devices"</string>
+ <string name="root_type_apps" msgid="8646073235029886342">"More apps"</string>
+ <string name="empty" msgid="5300254272613103004">"No items"</string>
+ <string name="no_results" msgid="2371026325236359209">"No matches in %1$s"</string>
+ <string name="toast_no_application" msgid="7555319548595113121">"Can’t open file"</string>
+ <string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Cannot open files in archives"</string>
+ <string name="toast_failed_delete" msgid="3453846588205817591">"Unable to delete some documents"</string>
+ <string name="share_via" msgid="8725082736005677161">"Share via"</string>
+ <string name="copy_notification_title" msgid="52256435625098456">"Copying files"</string>
+ <string name="compress_notification_title" msgid="6830195148113751021">"Compressing files"</string>
+ <string name="extract_notification_title" msgid="5067393961754430469">"Extracting files"</string>
+ <string name="move_notification_title" msgid="3173424987049347605">"Moving files"</string>
+ <string name="delete_notification_title" msgid="2512757431856830792">"Deleting files"</string>
+ <string name="copy_remaining" msgid="5390517377265177727">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
+ <plurals name="copy_begin" formatted="false" msgid="151184708996738192">
+ <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
+ <item quantity="one">Copying <xliff:g id="COUNT_0">%1$d</xliff:g> item.</item>
+ </plurals>
+ <plurals name="compress_begin" formatted="false" msgid="3534158317098678895">
+ <item quantity="other">Compressing <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
+ <item quantity="one">Compressing <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+ </plurals>
+ <plurals name="extract_begin" formatted="false" msgid="1006380679562903749">
+ <item quantity="other">Extracting <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
+ <item quantity="one">Extracting <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+ </plurals>
+ <plurals name="move_begin" formatted="false" msgid="1464229874265756956">
+ <item quantity="other">Moving <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
+ <item quantity="one">Moving <xliff:g id="COUNT_0">%1$d</xliff:g> item.</item>
+ </plurals>
+ <plurals name="deleting" formatted="false" msgid="1729138001178158901">
+ <item quantity="other">Deleting <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
+ <item quantity="one">Deleting <xliff:g id="COUNT_0">%1$d</xliff:g> item.</item>
+ </plurals>
+ <string name="undo" msgid="2902438994196400565">"Undo"</string>
+ <string name="copy_preparing" msgid="5326063807006898223">"Preparing for copy…"</string>
+ <string name="compress_preparing" msgid="6650018601382062672">"Preparing for compress…"</string>
+ <string name="extract_preparing" msgid="58266275455027829">"Preparing for extract…"</string>
+ <string name="move_preparing" msgid="8742573245485449429">"Preparing for move…"</string>
+ <string name="delete_preparing" msgid="6513863752916028147">"Preparing for delete…"</string>
+ <string name="delete_progress" msgid="2627631054702306423">"<xliff:g id="COUNT_0">%1$d</xliff:g> / <xliff:g id="TOTALCOUNT">%2$d</xliff:g>"</string>
+ <plurals name="copy_error_notification_title" formatted="false" msgid="3188432450429390963">
+ <item quantity="other">Couldn’t copy <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one">Couldn’t copy <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <plurals name="compress_error_notification_title" formatted="false" msgid="3043630066678213644">
+ <item quantity="other">Couldn’t compress <xliff:g id="COUNT_1">%1$d</xliff:g> files</item>
+ <item quantity="one">Couldn’t compress <xliff:g id="COUNT_0">%1$d</xliff:g> file</item>
+ </plurals>
+ <plurals name="move_error_notification_title" formatted="false" msgid="2185736082411854754">
+ <item quantity="other">Couldn’t move <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one">Couldn’t move <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <plurals name="delete_error_notification_title" formatted="false" msgid="7568122018481625267">
+ <item quantity="other">Couldn’t delete <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one">Couldn’t delete <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <string name="notification_touch_for_details" msgid="2385563502445129570">"Tap to view details"</string>
+ <string name="close" msgid="905969391788869975">"Close"</string>
+ <plurals name="copy_failure_alert_content" formatted="false" msgid="5570549471912990536">
+ <item quantity="other">These files weren’t copied: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t copied: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="compress_failure_alert_content" formatted="false" msgid="5760632881868842400">
+ <item quantity="other">These files weren’t compressed: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t compressed: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="extract_failure_alert_content" formatted="false" msgid="7572748127571720803">
+ <item quantity="other">These files weren’t extracted: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t extracted: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="move_failure_alert_content" formatted="false" msgid="2747390342670799196">
+ <item quantity="other">These files weren’t moved: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t moved: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="delete_failure_alert_content" formatted="false" msgid="6122372614839711711">
+ <item quantity="other">These files weren’t deleted: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file wasn’t deleted: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="copy_converted_warning_content" formatted="false" msgid="7433742181712126588">
+ <item quantity="other">These files were converted to another format: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">This file was converted to another format: <xliff:g id="LIST_0">%1$s</xliff:g></item>
+ </plurals>
+ <plurals name="clipboard_files_clipped" formatted="false" msgid="4847061634862926902">
+ <item quantity="other">Copied <xliff:g id="COUNT_1">%1$d</xliff:g> items to clipboard.</item>
+ <item quantity="one">Copied <xliff:g id="COUNT_0">%1$d</xliff:g> item to clipboard.</item>
+ </plurals>
+ <string name="file_operation_rejected" msgid="4301554203329008794">"File operation is not supported."</string>
+ <string name="file_operation_error" msgid="2234357335716533795">"File operation failed."</string>
+ <string name="rename_error" msgid="6700093173508118635">"Failed to rename document"</string>
+ <string name="menu_eject_root" msgid="9215040039374893613">"Eject"</string>
+ <string name="notification_copy_files_converted_title" msgid="6916768494891833365">"Some files were converted"</string>
+ <string name="open_external_dialog_request" msgid="8173558471322861268">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
+ <string name="open_external_dialog_root_request" msgid="6776729293982633">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
+ <string name="never_ask_again" msgid="525908236522201138">"Don\'t ask again"</string>
+ <string name="allow" msgid="1275746941353040309">"Allow"</string>
+ <string name="deny" msgid="5127201668078153379">"Deny"</string>
+ <plurals name="elements_selected" formatted="false" msgid="4448165978637163692">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
+ </plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="5932571296037626279">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
+ <string name="delete_filename_confirmation_message" msgid="8338069763240613258">"Delete \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="9084085260877704140">"Delete folder \"<xliff:g id="NAME">%1$s</xliff:g>\" and its contents?"</string>
+ <plurals name="delete_files_confirmation_message" formatted="false" msgid="4866664063250034142">
+ <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+ <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
+ <plurals name="delete_folders_confirmation_message" formatted="false" msgid="1028946402799686388">
+ <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> folders and their contents?</item>
+ <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> folder and its contents?</item>
+ </plurals>
+ <plurals name="delete_items_confirmation_message" formatted="false" msgid="7285090426511028179">
+ <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> items?</item>
+ <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> item?</item>
+ </plurals>
+ <string name="images_shortcut_label" msgid="2545168016070493574">"Images"</string>
+ <string name="archive_loading_failed" msgid="7243436722828766996">"Unable to open archive for browsing. File is either corrupt, or an unsupported format."</string>
+ <string name="name_conflict" msgid="28407269328862986">"A file with this name already exists."</string>
+ <string name="authentication_required" msgid="8030880723643436099">"To view this directory, sign in to <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="cant_display_content" msgid="8633226333229417237">"Can’t display contents"</string>
+ <string name="sign_in" msgid="6253762676723505592">"Sign in"</string>
+ <string name="new_archive_file_name" msgid="1604650338077249838">"archive<xliff:g id="EXTENSION">%s</xliff:g>"</string>
+ <string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"Overwrite <xliff:g id="NAME">%1$s</xliff:g>?"</string>
+ <string name="continue_in_background" msgid="1974214559047793331">"Continue in background"</string>
+</resources>
diff --git a/res/values-es-rUS/inspector_strings.xml b/res/values-es-rUS/inspector_strings.xml
new file mode 100644
index 0000000..e82d604
--- /dev/null
+++ b/res/values-es-rUS/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Información"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"No se pudo cargar la información del archivo"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Información de depuración (solo programadores)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadatos RAW: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalles del contenido multimedia"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Este tipo de archivo se abre con"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Proveedor del archivo:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Sin seleccionar"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Desconocido"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensiones"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> (<xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP)"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordenadas"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitud"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Cámara"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Apertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocidad del obturador"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duración"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Fecha de la foto"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Longitud focal"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Equivalente ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Álbum"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Ubicación"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipos de flujo"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Tamaño del archivo RAW (bytes)"</string>
+</resources>
diff --git a/res/values-es-rUS/mimes.xml b/res/values-es-rUS/mimes.xml
new file mode 100644
index 0000000..6cb9827
--- /dev/null
+++ b/res/values-es-rUS/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Archivo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Archivo"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imagen"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imagen <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archivo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicación de Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texto sin formato"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Documento HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Documento PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Documento de Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Presentación PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Hoja de cálculo de Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Documento de Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Hoja de cálculo Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Presentación de Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Dibujo de Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabla de Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulario de Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa de Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Sitio de Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Carpeta"</string>
+</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 27e249a..07d660e 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimir"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extraer en…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Cambiar nombre"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propiedades"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Obtener información"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Ver en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Ventana nueva"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cortar"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mover"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Descartar"</string>
<string name="button_retry" msgid="4011461781916631389">"Volver a intentar"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Borrar"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostrar en el proveedor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sin ordernar"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nombre"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Resumen"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Tamaño"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modificación"</string>
- <string name="directory_children" msgid="8115290268549503262">"Cantidad de hijos"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Cantidad de elementos"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascendente"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descendente"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostrar raíces"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"No se puede abrir el archivo"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"No se pueden abrir los documentos en Archivos"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"No es posible borrar algunos documentos"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"No se pudieron cargar las propiedades"</string>
<string name="share_via" msgid="8725082736005677161">"Compartir con"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copiando archivos"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Comprimiendo archivos"</string>
diff --git a/res/values-es/inspector_strings.xml b/res/values-es/inspector_strings.xml
new file mode 100644
index 0000000..fcd3d88
--- /dev/null
+++ b/res/values-es/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Información"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"No se ha podido cargar la información del archivo"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Información de depuración (solo desarrolladores)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadatos sin procesar: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalles de contenido multimedia"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Este tipo de archivo se abre con"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Proveedor del archivo:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"No se ha seleccionado"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Desconocida"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensiones"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g>x<xliff:g id="HEIGHT">%2$d</xliff:g> (<xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP)"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordenadas"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitud"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Cámara"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Apertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocidad del obturador"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duración"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Fecha de la foto"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Longitud focal"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Equivalente ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Álbum"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Ubicación"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stream types"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Tamaño del archivo RAW (bytes)"</string>
+</resources>
diff --git a/res/values-es/mimes.xml b/res/values-es/mimes.xml
new file mode 100644
index 0000000..eb2e016
--- /dev/null
+++ b/res/values-es/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Archivo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Archivo"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imagen"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imagen <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vídeo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vídeo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archivo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicación de Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texto sin formato"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Documento HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Documento PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Documento de Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Presentación PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Hoja de cálculo Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Documento de Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Hoja de cálculo Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Presentación de Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Dibujo de Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabla de Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulario de Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa de Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Sitio de Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Carpeta"</string>
+</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 6858822..636df57 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimir"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extraer a…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Cambiar nombre"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propiedades"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Obtener información"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Ver en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nueva ventana"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cortar"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mover"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Descartar"</string>
<string name="button_retry" msgid="4011461781916631389">"Volver a intentarlo"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Borrar"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostrar en el proveedor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sin ordenar"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nombre"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Resumen"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Tamaño"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modificado"</string>
- <string name="directory_children" msgid="8115290268549503262">"Número de hijos"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Número de elementos"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascendente"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descendente"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostrar raíces"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"No se puede abrir el archivo"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"No se pueden abrir los elementos archivados"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Error al eliminar algunos documentos"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"No se han podido cargar las propiedades"</string>
<string name="share_via" msgid="8725082736005677161">"Compartir a través de"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copiando archivos"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Comprimiendo archivos"</string>
diff --git a/res/values-et/inspector_strings.xml b/res/values-et/inspector_strings.xml
new file mode 100644
index 0000000..010cf9a
--- /dev/null
+++ b/res/values-et/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Teave"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Faili teavet ei saanud laadida"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Silumisteave (ainult arendajatele)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Toormetaandmed: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Meedia üksikasjad"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Seda tüüpi faile saab avada rakendusega"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Selle faili allikas on"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Pole valitud"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Teadmata"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Mõõtmed"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinaadid"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Kõrgus"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kaamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Ava"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Säriaeg"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Kestus"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Jäädvustatud"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Fookuskaugus"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Esitaja"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Helilooja"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Asukoht"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Voo tüübid"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Toorandmete maht (baitides)"</string>
+</resources>
diff --git a/res/values-et/mimes.xml b/res/values-et/mimes.xml
new file mode 100644
index 0000000..ab84b18
--- /dev/null
+++ b/res/values-et/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-fail"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fail"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Kujutis"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-kujutis"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Heli"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-helifail"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-videofail"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-arhiiv"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Androidi rakendus"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Lihttekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Wordi dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPointi esitlus"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Exceli arvutustabel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google\'i dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google\'i arvutustabel"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google\'i esitlus"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google\'i joonis"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google\'i tabel"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google\'i vorm"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google\'i kaart"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google\'i sait"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Kaust"</string>
+</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 253220a..e86fcd5 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Tihenda"</string>
<string name="menu_extract" msgid="8171946945982532262">"Ekstrakti …"</string>
<string name="menu_rename" msgid="1883113442688817554">"Nimeta ümber"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Atribuudid"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Teabe hankimine"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Kuva allikas <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Uus aken"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Lõika"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Teisalda"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Loobu"</string>
<string name="button_retry" msgid="4011461781916631389">"Proovi uuesti"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Kustuta"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Kuva teenuses"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sortimata"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nimi"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Kokkuvõte"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tüüp"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Suurus"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Muudetud"</string>
- <string name="directory_children" msgid="8115290268549503262">"Laste arv"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Üksuste arv"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Kasvav"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Kahanev"</string>
<string name="drawer_open" msgid="8071673398187261741">"Kuva juured"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Faili ei saa avada"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Arhiivides olevaid faile ei saa avada"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Mõnda dokumenti ei saa kustutada"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Atribuute ei saanud laadida"</string>
<string name="share_via" msgid="8725082736005677161">"Jaga rakendusega"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Failide kopeerimine"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Failide tihendamine"</string>
diff --git a/res/values-eu/inspector_strings.xml b/res/values-eu/inspector_strings.xml
new file mode 100644
index 0000000..24b9b4a
--- /dev/null
+++ b/res/values-eu/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informazioa"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Ezin izan da kargatu fitxategiaren informazioa"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Arazte-informazioa (garatzaileentzat soilik)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Prozesatu gabeko metadatuak: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Multimedia-elementuaren xehetasunak"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Mota honetako fitxategiak aplikazio honekin ireki daitezke:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Fitxategiaren hornitzailea:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Hautatu gabe"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Ezezaguna"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimentsioak"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordenatuak"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitudea"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Irekidura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Kliskagailuaren abiadura"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Iraupena"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Data"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Foku-distantzia"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO baliokidea"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Konpositorea"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albuma"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Kokapena"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Jario motak"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Prozesatu gabeko tamaina (byte-tan)"</string>
+</resources>
diff --git a/res/values-eu/mimes.xml b/res/values-eu/mimes.xml
new file mode 100644
index 0000000..45294b7
--- /dev/null
+++ b/res/values-eu/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> fitxategia"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fitxategia"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Irudia"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> irudia"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audioa"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audioa"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Bideoa"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> bideoa"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> artxiboa"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android aplikazioa"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Testu arrunta"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML dokumentua"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF dokumentua"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word dokumentua"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint aurkezpena"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel kalkulu-orria"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google dokumentua"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google kalkulu-orria"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google aurkezpena"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google marrazkia"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google taula"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google inprimakia"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google mapa"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google webgunea"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Karpeta"</string>
+</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 0196379..7c3deee 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Konprimatu"</string>
<string name="menu_extract" msgid="8171946945982532262">"Atera hona…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Aldatu izena"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propietateak"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Lortu informazioa"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Ikusi <xliff:g id="SOURCE">%1$s</xliff:g> zerbitzuan"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Leiho berria"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Ebaki"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mugitu"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Baztertu"</string>
<string name="button_retry" msgid="4011461781916631389">"Saiatu berriro"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Garbitu"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Erakutsi hornitzailean"</string>
<string name="not_sorted" msgid="7813496644889115530">"Ordenatu gabe"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Izena"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Laburpena"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Mota"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Tamaina"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Aldatze-ordua"</string>
- <string name="directory_children" msgid="8115290268549503262">"Haur kopurua"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Elementu kopurua"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Gorantz"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Beherantz"</string>
<string name="drawer_open" msgid="8071673398187261741">"Erakutsi erroko karpetak"</string>
@@ -81,8 +83,7 @@
<string name="no_results" msgid="2371026325236359209">"Ez da aurkitu ezer %1$s atalean"</string>
<string name="toast_no_application" msgid="7555319548595113121">"Ezin da ireki fitxategia"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Ezin dira ireki artxiboetako fitxategiak"</string>
- <string name="toast_failed_delete" msgid="3453846588205817591">"Ezin izan dira ezabatu dokumentu batzuk"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Ezin izan dira kargatu propietateak"</string>
+ <string name="toast_failed_delete" msgid="3453846588205817591">"Ezin dira ezabatu dokumentu batzuk"</string>
<string name="share_via" msgid="8725082736005677161">"Partekatu honekin:"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopiatu fitxategiak"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Fitxategiak konprimatzen"</string>
diff --git a/res/values-fa/inspector_strings.xml b/res/values-fa/inspector_strings.xml
new file mode 100644
index 0000000..e6daea3
--- /dev/null
+++ b/res/values-fa/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"اطلاعات"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"اطلاعات فایل بارگیری نشد"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"اطلاعات اشکالزدایی (فقط برنامهنویس)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"فراداده فایل Raw: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"جزئیات رسانه"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"این نوع فایل با این برنامه باز میشود"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ارائهدهنده این فایل"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"انتخاب نشده است"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"نامشخص"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ابعاد"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>مگاپیکسل"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"مختصات"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>، <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ارتفاع"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"دوربین"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"دیافراگم"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"سرعت شاتر"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"مدتزمان"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"گرفتهشده در"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"فیلم کامل"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>میلیمتر"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"معادل ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"<xliff:g id="ISO_SPEED">%1$d</xliff:g> ISO"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"هنرمند"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"آهنگساز"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"آلبوم"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"مکان"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"انواع پخش جریانی"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"حجم فایل RAW (بایت)"</string>
+</resources>
diff --git a/res/values-fa/mimes.xml b/res/values-fa/mimes.xml
new file mode 100644
index 0000000..1fc105e
--- /dev/null
+++ b/res/values-fa/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"فایل <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"فایل"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"تصویر"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"تصویر <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"فایل صوتی"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"فایل صوتی <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ویدئو"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"ویدئوی <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"بایگانی <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"برنامه Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"متن ساده"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"سند HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"سند PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"سند Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"ارائه PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"صفحهگسترده Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"سند Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"صفحهگسترده Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"ارائه Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"طرحنگار Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"جدول Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"فرمنگار Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google Map"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"پوشه"</string>
+</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 8185604..5417179 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"فشرده کردن"</string>
<string name="menu_extract" msgid="8171946945982532262">"استخراج در…"</string>
<string name="menu_rename" msgid="1883113442688817554">"تغییر نام"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"مشخصات"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"دریافت اطلاعات"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"مشاهده در <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"پنجره جدید"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"برش"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"انتقال"</string>
<string name="button_dismiss" msgid="7235249361023803349">"رد کردن"</string>
<string name="button_retry" msgid="4011461781916631389">"دوباره امتحان کنید"</string>
+ <string name="button_clear" msgid="5412304437764369441">"پاک کردن"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"نمایش در برنامه ارائهدهنده"</string>
<string name="not_sorted" msgid="7813496644889115530">"مرتبسازی نشده است"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"نام"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"خلاصه"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"نوع"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"اندازه"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"آخرین تغییر"</string>
- <string name="directory_children" msgid="8115290268549503262">"تعداد کودکان"</string>
+ <string name="directory_items" msgid="6645621978998614003">"تعداد موارد"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"صعودی"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"نزولی"</string>
<string name="drawer_open" msgid="8071673398187261741">"نمایش ریشهها"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"فایل باز نمیشود"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"فایلهای موجود در بایگانیها باز نمیشوند"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"برخی از اسناد حذف نمیشوند"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"مشخصات بار نشدند"</string>
<string name="share_via" msgid="8725082736005677161">"اشتراکگذاری از طریق"</string>
<string name="copy_notification_title" msgid="52256435625098456">"در حال کپی کردن فایلها"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"درحال فشردهسازی فایلها"</string>
diff --git a/res/values-fi/inspector_strings.xml b/res/values-fi/inspector_strings.xml
new file mode 100644
index 0000000..1e18204
--- /dev/null
+++ b/res/values-fi/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Tietoja"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Tiedoston tietojen lataus epäonnistui."</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Vianetsintätiedot (vain kehittäjät)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raa\'at sisällönkuvaustiedot: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Median tiedot"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Sovellus, jolla tiedostotyyppi avataan"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Tiedoston lähde"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Ei valittu"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Tuntematon"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Mitat"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinaatit"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Korkeus"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aukko"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Suljinaika"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Kesto"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Kuvaushetki"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Polttoväli"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-vastine"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artisti"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Säveltäjä"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albumi"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Sijainti"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Striimaustyypit"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raaka koko (tavua)"</string>
+</resources>
diff --git a/res/values-fi/mimes.xml b/res/values-fi/mimes.xml
new file mode 100644
index 0000000..64cab9a
--- /dev/null
+++ b/res/values-fi/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-tiedosto"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Tiedosto"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Kuva"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-kuva"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Ääni"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-ääni"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-arkisto"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-sovellus"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Pelkkä teksti"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-dokumentti"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-dokumentti"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-dokumentti"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-esitys"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-laskentataulukko"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-dokumentti"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-laskentataulukko"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-esitys"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-piirros"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-taulukko"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-lomake"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-kartta"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-sivusto"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Kansio"</string>
+</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index fe0fc2e..a23dd94 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Pakkaa"</string>
<string name="menu_extract" msgid="8171946945982532262">"Pura kohteeseen…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Nimeä uudelleen"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Ominaisuudet"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Näytä tiedot"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Avaa sovelluksella <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Uusi ikkuna"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Leikkaa"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Siirrä"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Hylkää"</string>
<string name="button_retry" msgid="4011461781916631389">"Yritä uudelleen"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Tyhjennä"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Näytä palveluntarjoajan sovelluksessa"</string>
<string name="not_sorted" msgid="7813496644889115530">"Ei lajittelua"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nimi"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Yhteenveto"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tyyppi"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Koko"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Muokattu"</string>
- <string name="directory_children" msgid="8115290268549503262">"Lasten määrä"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Kohteiden määrä"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Nouseva"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Laskeva"</string>
<string name="drawer_open" msgid="8071673398187261741">"Näytä juuret"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Tiedoston avaaminen epäonnistui."</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Arkistoissa olevia tiedostoja ei voi avata."</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Joidenkin dokumenttien poistaminen epäonnistui."</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Ominaisuuksien lataaminen epäonnistui."</string>
<string name="share_via" msgid="8725082736005677161">"Jaa sovelluksessa"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopioidaan tiedostoja"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Pakataan tiedostoja"</string>
diff --git a/res/values-fr-rCA/inspector_strings.xml b/res/values-fr-rCA/inspector_strings.xml
new file mode 100644
index 0000000..d4de841
--- /dev/null
+++ b/res/values-fr-rCA/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Renseignements"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Impossible de charger les renseignements sur le fichier"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Données de débogage (concepteurs uniquement)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Métadonnées brutes : <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Détails des médias"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ce type de fichier s\'ouvre avec"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Ce fichier est fourni par"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Non sélectionné"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Inconnu"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Mpx"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordonnées"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Appareil photo"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MODEL">%2$s</xliff:g> de <xliff:g id="MAKE">%1$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Ouverture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Vitesse de l\'obturateur"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Durée"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Prise le"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Distance focale"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Équivalent ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artiste"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositeur"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Localisation"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Types de flux"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Taille brute (en octets)"</string>
+</resources>
diff --git a/res/values-fr-rCA/mimes.xml b/res/values-fr-rCA/mimes.xml
new file mode 100644
index 0000000..47f07c7
--- /dev/null
+++ b/res/values-fr-rCA/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Fichier <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fichier"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Image"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Image <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vidéo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vidéo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archive <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Application Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texte brut"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Document HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Document PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Document Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Présentation PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Feuille de calcul Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Document Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Feuille de calcul Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Présentation Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Dessin Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tableau Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulaire Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Carte Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Site Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Dossier"</string>
+</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 1f59cb5..66a68fb 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Compresser"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extraire vers…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Renommer"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propriétés"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"En savoir plus"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Afficher dans <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nouvelle fenêtre"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Couper"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Déplacer"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Fermer"</string>
<string name="button_retry" msgid="4011461781916631389">"Réessayer"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Effacer"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Afficher dans l\'application du fournisseur"</string>
<string name="not_sorted" msgid="7813496644889115530">"Non trié"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nom"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Résumé"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Taille"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Dernière modification"</string>
- <string name="directory_children" msgid="8115290268549503262">"Nombre d\'enfants"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Nombre d\'éléments"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Par ordre croissant"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Par ordre décroissant"</string>
<string name="drawer_open" msgid="8071673398187261741">"Afficher les racines"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Impossible d\'ouvrir le fichier"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Impossible d\'ouvrir des fichiers dans les archives"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Impossible de supprimer certains documents"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Les propriétés n\'ont pas pu être chargées"</string>
<string name="share_via" msgid="8725082736005677161">"Partager via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copie de fichiers…"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compression des fichiers"</string>
diff --git a/res/values-fr/inspector_strings.xml b/res/values-fr/inspector_strings.xml
new file mode 100644
index 0000000..b2fa481
--- /dev/null
+++ b/res/values-fr/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informations"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Impossible de charger les informations relatives au fichier"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informations de débogage (développeur seulement)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Métadonnées brutes : <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Informations sur les médias"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ce type de fichier s\'ouvre avec"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Ce fichier est fourni par"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Non sélectionnée"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Inconnue"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensions"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Mpx"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordonnées"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Appareil photo"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Ouverture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Vitesse d\'obturation"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Durée"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Prise le"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Longueur focale"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Équivalent ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artiste"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositeur"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Localisation"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Types de flux"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Taille brute (octets)"</string>
+</resources>
diff --git a/res/values-fr/mimes.xml b/res/values-fr/mimes.xml
new file mode 100644
index 0000000..47f07c7
--- /dev/null
+++ b/res/values-fr/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Fichier <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fichier"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Image"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Image <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vidéo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vidéo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archive <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Application Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texte brut"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Document HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Document PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Document Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Présentation PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Feuille de calcul Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Document Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Feuille de calcul Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Présentation Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Dessin Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tableau Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulaire Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Carte Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Site Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Dossier"</string>
+</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index d0a96ee..73048ab 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Compresser"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extraire sur…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Renommer"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propriétés"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Obtenir les informations"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Afficher dans <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nouvelle fenêtre"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Couper"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Déplacer"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ignorer"</string>
<string name="button_retry" msgid="4011461781916631389">"Réessayer"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Effacer"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Afficher dans le fournisseur"</string>
<string name="not_sorted" msgid="7813496644889115530">"Non triés"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nom"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Résumé"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Taille"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Dernière modif."</string>
- <string name="directory_children" msgid="8115290268549503262">"Nombre d\'enfants"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Nombre d\'éléments"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Croissant"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Décroissant"</string>
<string name="drawer_open" msgid="8071673398187261741">"Afficher les répertoires racines"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Impossible d\'ouvrir le fichier"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Impossible d\'ouvrir un fichier dans une archive"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Impossible de supprimer certains documents"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Impossible de charger les propriétés"</string>
<string name="share_via" msgid="8725082736005677161">"Partager via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copie de fichiers…"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compression de fichiers"</string>
diff --git a/res/values-gl/inspector_strings.xml b/res/values-gl/inspector_strings.xml
new file mode 100644
index 0000000..a33b561
--- /dev/null
+++ b/res/values-gl/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Información"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Non se puido cargar a información do ficheiro"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Datos de depuración (só para programadores)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadatos sen procesar: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Datos multimedia"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Este tipo de ficheiro ábrese con"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Provedor do ficheiro"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Non seleccionada"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Descoñecida"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensións"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> (<xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Mpx)"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordenadas"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Cámara"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MODEL">%2$s</xliff:g> de <xliff:g id="MAKE">%1$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Abertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocidade do obturador"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duración"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Data da foto"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Distancia focal"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Equivalente ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Álbum"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Localización"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipos de emisión"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Tamaño sen procesar (bytes)"</string>
+</resources>
diff --git a/res/values-gl/mimes.xml b/res/values-gl/mimes.xml
new file mode 100644
index 0000000..05b48c4
--- /dev/null
+++ b/res/values-gl/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Ficheiro <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Ficheiro"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imaxe"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imaxe <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vídeo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vídeo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arquivo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicación Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texto sen formato"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Documento HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Documento PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Documento de Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Presentación PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Folla de cálculo Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Documento de Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Folla de cálculo Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Presentación de Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Debuxo de Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Táboa de Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulario de Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa de Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Sitio de Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Cartafol"</string>
+</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 2f2d5e1..606af08 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimir"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extraer en..."</string>
<string name="menu_rename" msgid="1883113442688817554">"Cambiar nome"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propiedades"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Obter información"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Ver en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nova ventá"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cortar"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mover"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ignorar"</string>
<string name="button_retry" msgid="4011461781916631389">"Tentar de novo"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Borrar"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostrar no provedor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sen ordenar"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nome"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Resumo"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Tamaño"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modificado"</string>
- <string name="directory_children" msgid="8115290268549503262">"Número de nenos"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Número de elementos"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascendente"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descendente"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostrar raíces"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Non se pode abrir o ficheiro"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Non se poden abrir ficheiros dentro de arquivos"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Non se poden eliminar algúns documentos"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Non se puideron cargar as propiedades"</string>
<string name="share_via" msgid="8725082736005677161">"Compartir a través de"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copiando ficheiros"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Comprimindo ficheiros"</string>
diff --git a/res/values-gu/inspector_strings.xml b/res/values-gu/inspector_strings.xml
new file mode 100644
index 0000000..97e0b8a
--- /dev/null
+++ b/res/values-gu/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"માહિતી"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ફાઇલની માહિતી લોડ કરી શકાતી નથી"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ડિબગ માહિતી (માત્ર વિકાસકર્તા)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw મેટાડેટા: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"મીડિયા વિગતો"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"આની સાથે આ પ્રકારની ફાઇલ ખૂલે છે"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"આ ફાઇલ આમના દ્વારા પૂરી પાડવામાં આવી"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"પસંદ કર્યું નથી"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"અજાણ"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"પરિમાણો"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"કોઓર્ડિનેટ્સ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ઊંચાઈ"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"કૅમેરા"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"ઍપર્ચર"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"શટરની સ્પીડ"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"અવધિ"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ના રોજ લીધેલો"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ફોકલ લંબાઈ"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>મિમી"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO સમકક્ષ"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"કલાકાર"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"સંગીતકાર"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"આલ્બમ"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"સ્થાન"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"સ્ટ્રીમના પ્રકારો"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Rawનું કદ (બાઇટ)"</string>
+</resources>
diff --git a/res/values-gu/mimes.xml b/res/values-gu/mimes.xml
new file mode 100644
index 0000000..97e9224
--- /dev/null
+++ b/res/values-gu/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ફાઇલ"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ફાઇલ"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"છબી"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> છબી"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ઑડિઓ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ઑડિઓ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"વીડિઓ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> વીડિઓ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> આર્કાઇવ"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android ઍપ્લિકેશન"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"સાદી ટેક્સ્ટ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML દસ્તાવેજ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF દસ્તાવેજ"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word દસ્તાવેજ"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint પ્રસ્તુતિ"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel સ્પ્રેડશીટ"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google દસ્તાવેજ"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google સ્પ્રેડશીટ"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google પ્રસ્તુતિ"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ડ્રોઇંગ"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google કોષ્ટક"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ફોર્મ"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google નકશો"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google સાઇટ"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ફોલ્ડર"</string>
+</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index f61a9c4..c2116c4 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"સંકુચિત કરો"</string>
<string name="menu_extract" msgid="8171946945982532262">"આમાં એક્સટ્રેક્ટ કરો…"</string>
<string name="menu_rename" msgid="1883113442688817554">"નામ બદલો"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"ગુણધર્મો"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"માહિતી મેળવો"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g>માં જુઓ"</string>
<string name="menu_new_window" msgid="2947837751796109126">"નવી વિંડો"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"કાપો"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ખસેડો"</string>
<string name="button_dismiss" msgid="7235249361023803349">"છોડી દો"</string>
<string name="button_retry" msgid="4011461781916631389">"ફરી પ્રયાસ કરો"</string>
+ <string name="button_clear" msgid="5412304437764369441">"સાફ કરો"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"પ્રદાતા સેવામાં બતાવો"</string>
<string name="not_sorted" msgid="7813496644889115530">"સૉર્ટ કરેલ નથી"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"નામ"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"સારાંશ"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"પ્રકાર"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"કદ"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"સંશોધિત"</string>
- <string name="directory_children" msgid="8115290268549503262">"બાળકોની સંખ્યા"</string>
+ <string name="directory_items" msgid="6645621978998614003">"આઇટમની સંખ્યા:"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ચઢતાં ક્રમમાં"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"ઉતરતા ક્રમમાં"</string>
<string name="drawer_open" msgid="8071673398187261741">"રૂટ્સ બતાવો"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ફાઇલ ખોલી શકતાં નથી"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"આર્કાઇવમાંની ફાઇલો ખોલી શકાતી નથી"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"કેટલાક દસ્તાવેજો કાઢી નાખવામાં અસમર્થ"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"પ્રોપર્ટી લોડ કરી શકાઈ નથી"</string>
<string name="share_via" msgid="8725082736005677161">"આના દ્વારા શેર કરો"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ફાઇલો કૉપિ કરી રહ્યાં છે"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ફાઇલોને સંકુચિત કરવી"</string>
@@ -170,7 +171,7 @@
<string name="notification_copy_files_converted_title" msgid="6916768494891833365">"કેટલીક ફાઇલો રૂપાંતરિત કરી હતી"</string>
<string name="open_external_dialog_request" msgid="8173558471322861268">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="STORAGE"><i>^3</i></xliff:g> પર <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> નિર્દેશિકાની ઍક્સેસ આપીએ?"</string>
<string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> નિર્દેશિકાની ઍક્સેસ આપીએ?"</string>
- <string name="open_external_dialog_root_request" msgid="6776729293982633">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="STORAGE"><i>^2</i></xliff:g> પર ફોટા અને વિડિઓઝ સહિત તમારા ડેટાની અૅક્સેસ આપીએ?"</string>
+ <string name="open_external_dialog_root_request" msgid="6776729293982633">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="STORAGE"><i>^2</i></xliff:g> પર ફોટો અને વિડિઓઝ સહિત તમારા ડેટાની અૅક્સેસ આપીએ?"</string>
<string name="never_ask_again" msgid="525908236522201138">"ફરીથી પૂછશો નહીં"</string>
<string name="allow" msgid="1275746941353040309">"મંજૂરી આપો"</string>
<string name="deny" msgid="5127201668078153379">"નકારો"</string>
diff --git a/res/values-hi/inspector_strings.xml b/res/values-hi/inspector_strings.xml
new file mode 100644
index 0000000..e18a792
--- /dev/null
+++ b/res/values-hi/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"जानकारी"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"फ़ाइल की जानकारी लोड नहीं हो सकी"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"डीबग जानकारी (केवल डेवलपर)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"अपरिष्कृत मेटाडेटा: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"मीडिया की जानकारी"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"इस तरह की फ़ाइल इसमें खुलती है:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"यह फ़ाइल यहां से उपलब्ध कराई गई है"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"नहीं चुना गया"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"अज्ञात"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"आयाम"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>एमपी"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"निर्देशांक"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ऊंचाई"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"कैमरा"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"एपर्चर"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"शटर की गति"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"अवधि"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"फ़ोटो लिए जाने का समय"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"फ़ोकल लंबाई"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> मिमी"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO के बराबर"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"कलाकार"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"संगीतकार"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"एल्बम"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"जगह"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"प्रसारण के प्रकार"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"अपरिष्कृत आकार (बाइट)"</string>
+</resources>
diff --git a/res/values-hi/mimes.xml b/res/values-hi/mimes.xml
new file mode 100644
index 0000000..ffff6e9
--- /dev/null
+++ b/res/values-hi/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> फ़ाइल"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"फ़ाइल"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"चित्र"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> चित्र"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ऑडियो"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ऑडियो"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"वीडियो"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> वीडियो"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> संग्रह"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android ऐप्लिकेशन"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"सादा पाठ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML दस्तावेज़"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"पीडीएफ़ दस्तावेज़"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word दस्तावेज़"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint प्रस्तुतिकरण"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel स्प्रैडशीट"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google दस्तावेज़"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google स्प्रैडशीट"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google प्रस्तुतिकरण"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google आरेखण"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google टेबल"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google फ़ॉर्म"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google मानचित्र"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google साइट"</string>
+ <string name="directory_type" msgid="2702987727566226354">"फ़ोल्डर"</string>
+</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 4924965..3ab5f55 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -23,25 +23,25 @@
<!-- no translation found for launcher_label (799410258349837668) -->
<skip />
<string name="title_open" msgid="3165686459158020921">"यहां से खोलें"</string>
- <string name="title_save" msgid="4384490653102710025">"यहां सहेजें"</string>
+ <string name="title_save" msgid="4384490653102710025">"यहां सेव करें"</string>
<string name="menu_create_dir" msgid="2413624798689091042">"नया फ़ोल्डर"</string>
<string name="menu_grid" msgid="1453636521731880680">"ग्रिड दृश्य"</string>
<string name="menu_list" msgid="6714267452146410402">"सूची दृश्य"</string>
- <string name="menu_search" msgid="1876699106790719849">"खोजें"</string>
+ <string name="menu_search" msgid="1876699106790719849">"सर्च करें"</string>
<string name="menu_settings" msgid="6520844520117939047">"जगह सेटिंग"</string>
<string name="menu_open" msgid="9092138100049759315">"खोलें"</string>
<string name="menu_open_with" msgid="5507647065467520229">"इसमें खोलें"</string>
<string name="menu_open_in_new_window" msgid="6686563636123311276">"नई विंडो में खोलें"</string>
- <string name="menu_save" msgid="5195367497138965168">"सहेजें"</string>
- <string name="menu_share" msgid="4307140947108068356">"साझा करें"</string>
- <string name="menu_delete" msgid="1022254131543256626">"हटाएं"</string>
+ <string name="menu_save" msgid="5195367497138965168">"सेव करें"</string>
+ <string name="menu_share" msgid="4307140947108068356">"शेयर करें"</string>
+ <string name="menu_delete" msgid="1022254131543256626">"मिटाएं"</string>
<string name="menu_select_all" msgid="7600576812185570403">"सभी चुनें"</string>
<string name="menu_copy" msgid="7404820171352314754">"इनकी कॉपी करें..."</string>
<string name="menu_move" msgid="2310760789561129882">"यहां ले जाएं…"</string>
<string name="menu_compress" msgid="37539111904724188">"कंप्रेस करें"</string>
<string name="menu_extract" msgid="8171946945982532262">"यहां निकालें…"</string>
<string name="menu_rename" msgid="1883113442688817554">"नाम बदलें"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"गुण"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"जानकारी पाएं"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> में देखें"</string>
<string name="menu_new_window" msgid="2947837751796109126">"नई विंडो"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"काटें"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ले जाएं"</string>
<string name="button_dismiss" msgid="7235249361023803349">"खारिज करें"</string>
<string name="button_retry" msgid="4011461781916631389">"फिर से कोशिश करें"</string>
+ <string name="button_clear" msgid="5412304437764369441">"साफ़ करें"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"प्रदाता में दिखाएं"</string>
<string name="not_sorted" msgid="7813496644889115530">"क्रमबद्ध नहीं हैं"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"नाम"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"सारांश"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"प्रकार"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"आकार"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"बदलनेे का समय"</string>
- <string name="directory_children" msgid="8115290268549503262">"बच्चों की संख्या"</string>
+ <string name="directory_items" msgid="6645621978998614003">"आइटम की संख्या"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"बढ़ते क्रम में"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"घटते क्रम में"</string>
<string name="drawer_open" msgid="8071673398187261741">"रूट दिखाएं"</string>
@@ -82,8 +84,7 @@
<string name="toast_no_application" msgid="7555319548595113121">"फ़ाइल नहीं खोली जा सकती"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"संग्रह में मौजूद फ़ाइलें नहीं खोली जा सकतीं"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"कुछ दस्तावेज़ों को हटाने में असमर्थ"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"प्रॉपर्टी लोड नहीं हो सकीं"</string>
- <string name="share_via" msgid="8725082736005677161">"इसके द्वारा साझा करें"</string>
+ <string name="share_via" msgid="8725082736005677161">"इसके ज़रिए शेयर करें"</string>
<string name="copy_notification_title" msgid="52256435625098456">"फ़ाइलें कॉपी हो रही हैं"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"फ़ाइलें कंप्रेस करना"</string>
<string name="extract_notification_title" msgid="5067393961754430469">"फ़ाइलें निकाली जा रही हैं"</string>
@@ -156,8 +157,8 @@
<item quantity="other">ये फ़ाइलें नहीं मिटाई गई थीं: <xliff:g id="LIST_1">%1$s</xliff:g></item>
</plurals>
<plurals name="copy_converted_warning_content" formatted="false" msgid="7433742181712126588">
- <item quantity="one">ये फ़ाइलें किसी और प्रारूप में बदल दी गई थीं: <xliff:g id="LIST_1">%1$s</xliff:g></item>
- <item quantity="other">ये फ़ाइलें किसी और प्रारूप में बदल दी गई थीं: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">ये फ़ाइलें किसी और फ़ॉर्मेट में बदल दी गई थीं: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="other">ये फ़ाइलें किसी और फ़ॉर्मेट में बदल दी गई थीं: <xliff:g id="LIST_1">%1$s</xliff:g></item>
</plurals>
<plurals name="clipboard_files_clipped" formatted="false" msgid="4847061634862926902">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> आइटम क्लिपबोर्ड पर कॉपी किए गए.</item>
@@ -168,9 +169,9 @@
<string name="rename_error" msgid="6700093173508118635">"दस्तावेज़ का नाम बदलना विफल रहा"</string>
<string name="menu_eject_root" msgid="9215040039374893613">"निकालें"</string>
<string name="notification_copy_files_converted_title" msgid="6916768494891833365">"कुछ फ़ाइलें रूपांतरित हो गई थीं"</string>
- <string name="open_external_dialog_request" msgid="8173558471322861268">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^3</i></xliff:g> पर <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिका का एक्सेस देना चाहते हैं?"</string>
- <string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिका का एक्सेस देना चाहते हैं?"</string>
- <string name="open_external_dialog_root_request" msgid="6776729293982633">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^2</i></xliff:g> पर मौजूद फ़ोटो और वीडियो सहित, अपने डेटा का एक्सेस देना चाहते हैं?"</string>
+ <string name="open_external_dialog_request" msgid="8173558471322861268">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^3</i></xliff:g> पर <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> डिक्शनरी तक पहुंचने देना चाहते हैं?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> डिक्शनरी तक पहुंचने देना चाहते हैं?"</string>
+ <string name="open_external_dialog_root_request" msgid="6776729293982633">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^2</i></xliff:g> पर मौजूद फ़ोटो और वीडियो के साथ, अपने डेटा तक पहुंचने देना चाहते हैं?"</string>
<string name="never_ask_again" msgid="525908236522201138">"फिर से ना पूछें"</string>
<string name="allow" msgid="1275746941353040309">"अनुमति दें"</string>
<string name="deny" msgid="5127201668078153379">"अस्वीकार करें"</string>
@@ -185,23 +186,23 @@
<string name="delete_filename_confirmation_message" msgid="8338069763240613258">"\"<xliff:g id="NAME">%1$s</xliff:g>\" को हटाना चाहते हैं?"</string>
<string name="delete_foldername_confirmation_message" msgid="9084085260877704140">"फ़ोल्डर \"<xliff:g id="NAME">%1$s</xliff:g>\" और उसकी सामग्रियों को हटाना चाहते हैं?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="4866664063250034142">
- <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें हटाएं?</item>
- <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें हटाएं?</item>
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें मिटाएं?</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें मिटाएं?</item>
</plurals>
<plurals name="delete_folders_confirmation_message" formatted="false" msgid="1028946402799686388">
- <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ोल्डर और उनकी सामग्री हटाएं?</item>
- <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ोल्डर और उनकी सामग्री हटाएं?</item>
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ोल्डर और उनकी सामग्री मिटाएं?</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ोल्डर और उनकी सामग्री मिटाएं?</item>
</plurals>
<plurals name="delete_items_confirmation_message" formatted="false" msgid="7285090426511028179">
- <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> आइटम हटाएं?</item>
- <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> आइटम हटाएं?</item>
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> आइटम मिटाएं?</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> आइटम मिटाएं?</item>
</plurals>
<string name="images_shortcut_label" msgid="2545168016070493574">"चित्र"</string>
- <string name="archive_loading_failed" msgid="7243436722828766996">"ब्राउज़िंग के लिए संग्रह खोलने में असमर्थ. फ़ाइल या तो दूषित हो गई है या असमर्थित प्रारूप में है."</string>
+ <string name="archive_loading_failed" msgid="7243436722828766996">"ब्राउज़िंग के लिए संग्रह नहीं खोला जा सका. फ़ाइल या तो इस्तेमाल के लायक नहीं रही या ऐसे फ़ॉर्मेट में है जो काम नहीं कर रहा."</string>
<string name="name_conflict" msgid="28407269328862986">"इस नाम की एक फ़ाइल पहले से मौजूद है."</string>
- <string name="authentication_required" msgid="8030880723643436099">"यह निर्देशिका देखने के लिए, <xliff:g id="NAME">%1$s</xliff:g> में प्रवेश करें"</string>
+ <string name="authentication_required" msgid="8030880723643436099">"यह डिक्शनरी देखने के लिए, <xliff:g id="NAME">%1$s</xliff:g> में साइन इन करें"</string>
<string name="cant_display_content" msgid="8633226333229417237">"सामग्रियां प्रदर्शित नहीं की जा सकतीं"</string>
- <string name="sign_in" msgid="6253762676723505592">"प्रवेश करें"</string>
+ <string name="sign_in" msgid="6253762676723505592">"साइन इन करें"</string>
<string name="new_archive_file_name" msgid="1604650338077249838">"संग्रह<xliff:g id="EXTENSION">%s</xliff:g>"</string>
<string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"<xliff:g id="NAME">%1$s</xliff:g> को ओवरराइट करना चाहते हैं?"</string>
<string name="continue_in_background" msgid="1974214559047793331">"बैकग्राउंड में जारी रखें"</string>
diff --git a/res/values-hr/inspector_strings.xml b/res/values-hr/inspector_strings.xml
new file mode 100644
index 0000000..3101ae1
--- /dev/null
+++ b/res/values-hr/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informacije"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Učitavanje informacija o datoteci nije uspjelo"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Podaci o otklanjanju pogrešaka (samo razvoj)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Neobrađeni metapodaci: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Pojedinosti o medijma"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ova se vrsta datoteke otvara aplikacijom"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Datoteku pruža"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nije odabrano"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Nepoznato"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimenzije"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Nadmorska visina"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Fotoaparat"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Otvor blende"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Brzina zatvarača"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Trajanje"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Snimljeno"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Žarišna duljina"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Izvođač"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Skladatelj"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokacija"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Vrste strujanja"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Neobrađena veličina (u bajtovima)"</string>
+</resources>
diff --git a/res/values-hr/mimes.xml b/res/values-hr/mimes.xml
new file mode 100644
index 0000000..44c9e28
--- /dev/null
+++ b/res/values-hr/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> datoteka"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Datoteka"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Slika"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> slika"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audiozapisi"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audiozapis"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Videozapisi"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> videozapis"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> arhiva"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android aplikacija"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Obični tekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint prezentacija"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel proračun. tablica"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google proračun. tablica"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google prezentacija"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google crtež"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google tablica"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google obrazac"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google karta"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google web-lokacija"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mapa"</string>
+</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 91a705f..b5315d2 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Sažmi"</string>
<string name="menu_extract" msgid="8171946945982532262">"Izdvoji u…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Promijeni naziv"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Svojstva"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Pogledajte informacije"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Prikaži na usluzi <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Novi prozor"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Izreži"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Premjesti"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Odbaci"</string>
<string name="button_retry" msgid="4011461781916631389">"Pokušaj ponovo"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Izbriši"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Prikaži na davatelju usluga"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nije poredano"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Naziv"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Sažetak"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Vrsta"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Veličina"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Izmijenjeno"</string>
- <string name="directory_children" msgid="8115290268549503262">"Broj djece"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Broj stavki"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Uzlazno"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Silazno"</string>
<string name="drawer_open" msgid="8071673398187261741">"Prikaži korijene"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Datoteka se ne može otvoriti"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Nije moguće otvoriti datoteke u arhivama"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nije moguće izbrisati neke dokumente"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Učitavanje svojstava nije uspjelo"</string>
<string name="share_via" msgid="8725082736005677161">"Dijeli putem"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopiranje datoteka"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Sažimanje datoteka"</string>
diff --git a/res/values-hu/inspector_strings.xml b/res/values-hu/inspector_strings.xml
new file mode 100644
index 0000000..b27149f
--- /dev/null
+++ b/res/values-hu/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Információ"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Nem sikerült betölteni a fájl információit"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Hibakeresési információ (csak fejlesztőknek)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"RAW-metaadatok: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Médiainformációk"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ezt a fájltípust a következő alkalmazás nyitja meg:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"A fájlt a következő biztosítja:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nincs kiválasztva"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Ismeretlen"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Méretek"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordináták"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Magasság"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Fényképezőgép"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Rekesz"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Záridő"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Időtartam"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Felvétel ideje:"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Fókusztávolság"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-egyenérték"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Előadó"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Zeneszerző"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Helyadatok"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Streamtípusok"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"RAW-méret (bájt)"</string>
+</resources>
diff --git a/res/values-hu/mimes.xml b/res/values-hu/mimes.xml
new file mode 100644
index 0000000..013e5ec
--- /dev/null
+++ b/res/values-hu/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-fájl"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fájl"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Kép"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-kép"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Hang"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-hang"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Videó"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-videó"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-archívum"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-alkalmazás"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Egyszerű szöveg"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-dokumentum"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-dokumentum"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-dokumentum"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-prezentáció"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-táblázat"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-dokumentum"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-táblázat"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-prezentáció"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-rajz"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-táblázat"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-űrlap"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-térkép"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-webhely"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mappa"</string>
+</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 2bc2d24..ed24c97 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Tömörítés"</string>
<string name="menu_extract" msgid="8171946945982532262">"Kicsomagolás ide…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Átnevezés"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Tulajdonságok"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Információ megjelenítése"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Megtekintés a következőben: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Új ablak"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Kivágás"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Áthelyezés"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Elvetés"</string>
<string name="button_retry" msgid="4011461781916631389">"Próbálja újra"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Törlés"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Megjelenítés a szolgáltatónál"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nincs rendezve"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Név"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Összefoglalás"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Típus"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Méret"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Módosítva"</string>
- <string name="directory_children" msgid="8115290268549503262">"Gyermekek száma"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Elemek száma"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Növekvő"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Csökkenő"</string>
<string name="drawer_open" msgid="8071673398187261741">"Gyökérszint megjelenítése"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"A fájlt nem lehet megnyitni"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Az archívumban nem lehet fájlokat megnyitni"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Néhány dokumentumot nem lehet törölni"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Nem sikerült betölteni a tulajdonságokat"</string>
<string name="share_via" msgid="8725082736005677161">"Megosztás itt:"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Fájlok másolása"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Fájlok tömörítése"</string>
diff --git a/res/values-hy/inspector_strings.xml b/res/values-hy/inspector_strings.xml
new file mode 100644
index 0000000..c13b686
--- /dev/null
+++ b/res/values-hy/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Տեղեկություններ"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Չհաջողվեց բեռնել ֆայլի տվյալները"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Վրիպազերծման տեղեկություններ (միայն մշակող)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw մետատվյալներ՝ <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Մեդիա տվյալներ"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Այս տեսակի ֆայլերի բացման հավելվածը"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Այս ֆայլի մատակարարը"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Ընտրված չէ"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Անհայտ է"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Չափեր"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$.1f</xliff:g> ՄՊ"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Կոորդինատներ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Բարձրություն"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Տեսախցիկ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Բացվածք"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Պահաժամ"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Տևողությունը"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Լուսանկարվել է՝"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Ֆոկուսային հեռավորությունը"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> մմ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-ի համարժեք"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Կատարող"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Կոմպոզիտոր"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Ալբոմ"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Գտնվելու վայրը"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Հոսքի տեսակներ"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw ֆայլի չափ (բայթ)"</string>
+</resources>
diff --git a/res/values-hy/mimes.xml b/res/values-hy/mimes.xml
new file mode 100644
index 0000000..660d7b3
--- /dev/null
+++ b/res/values-hy/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ֆայլ"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Ֆայլ"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Պատկեր"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> պատկեր"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Աուդիո"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> աուդիո"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Տեսանյութ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> տեսանյութ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> արխիվ"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android հավելված"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Հասարակ տեքստ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML փաստաթուղթ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF փաստաթուղթ"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word փաստաթուղթ"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint ներկայացում"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel աղյուսակ"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google փաստաթուղթ"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google աղյուսակ"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google ներկայացում"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google գծագիր"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google աղյուսակ"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ձև"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google քարտեզ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google կայք"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Պանակ"</string>
+</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 2156865..8d036a7 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Սեղմել"</string>
<string name="menu_extract" msgid="8171946945982532262">"Արտահանել…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Վերանվանել"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Հատկություններ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Տեղեկություններ"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Դիտել <xliff:g id="SOURCE">%1$s</xliff:g>-ում"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Նոր պատուհան"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Կտրել"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Տեղափոխել"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Փակել"</string>
<string name="button_retry" msgid="4011461781916631389">"Փորձել նորից"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Մաքրել"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Ցուցադրել մատակարարում"</string>
<string name="not_sorted" msgid="7813496644889115530">"Տեսակավորված չեն"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Անունը"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Ամփոփագիր"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Տեսակը"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Չափը"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Փոփոխվել է"</string>
- <string name="directory_children" msgid="8115290268549503262">"Երեխաների թիվը"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Տարրերի քանակ"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Աճման կարգով"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Նվազման կարգով"</string>
<string name="drawer_open" msgid="8071673398187261741">"Ցույց տալ արմատները"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Հնարավոր չէ բացել ֆայլը"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Հնարավոր չէ բացել արխիվացված ֆայլերը"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Հնարավոր չէ ջնջել որոշ փաստաթղթեր"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Հատկությունները հնարավոր չէ բեռնել"</string>
<string name="share_via" msgid="8725082736005677161">"Կիսվել"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Ֆայլերի պատճենում"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Ֆայլերի սեղմում"</string>
diff --git a/res/values-in/inspector_strings.xml b/res/values-in/inspector_strings.xml
new file mode 100644
index 0000000..0964060
--- /dev/null
+++ b/res/values-in/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Info"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Info file tidak dapat dimuat"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Info debug (khusus dev)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadata raw: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detail media"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"File jenis ini dibuka dengan"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"File ini diberikan oleh"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Tidak dipilih"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Tidak diketahui"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensi"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinat"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Ketinggian"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Bukaan"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Kecepatan rana"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Durasi"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Diambil pada"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Panjang fokal"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Setara ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artis"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Komposer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokasi"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Jenis streaming"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Ukuran raw (byte)"</string>
+</resources>
diff --git a/res/values-in/mimes.xml b/res/values-in/mimes.xml
new file mode 100644
index 0000000..a5664d5
--- /dev/null
+++ b/res/values-in/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"File <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Gambar"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Gambar <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arsip <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplikasi Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Teks biasa"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Dokumen HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Dokumen PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Dokumen Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Presentasi PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Spreadsheet Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Dokumen Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Spreadsheet Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Presentasi Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Gambar Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabel Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulir Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Peta Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Situs Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 0da9252..8ef3466 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Kompresi"</string>
<string name="menu_extract" msgid="8171946945982532262">"Ekstrak ke…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Ganti nama"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Properti"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Dapatkan info"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Lihat di <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Jendela baru"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Potong"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Pindahkan"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Tutup"</string>
<string name="button_retry" msgid="4011461781916631389">"Coba Lagi"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Hapus"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Tampilkan di provider"</string>
<string name="not_sorted" msgid="7813496644889115530">"Tidak diurutkan"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nama"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Ringkasan"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Jenis"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Ukuran"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Diubah"</string>
- <string name="directory_children" msgid="8115290268549503262">"Jumlah Anak"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Jumlah item"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Naik"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Turun"</string>
<string name="drawer_open" msgid="8071673398187261741">"Tampilkan root"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Tidak dapat membuka file"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Tidak dapat membuka file dalam arsip"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Tidak dapat menghapus beberapa dokumen"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Properti tidak dapat dimuat"</string>
<string name="share_via" msgid="8725082736005677161">"Bagikan melalui"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Menyalin file"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Mengompres file"</string>
diff --git a/res/values-is/inspector_strings.xml b/res/values-is/inspector_strings.xml
new file mode 100644
index 0000000..72dc56b
--- /dev/null
+++ b/res/values-is/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Upplýsingar"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Ekki var hægt að hlaða skráarupplýsingar"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Kembiupplýsingar (aðeins þróunaraðilar)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Óunnin lýsigögn: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Efnisupplýsingar"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Þessi tegund af skrá opnast með"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Veita þessarar skráar er:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Ekki valið"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Óþekkt"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Stærð"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Hnit"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Hæð"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Myndavél"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Ljósop"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Lokarahraði"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Tímalengd"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Tekin"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Brennivídd"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-jafngildi"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Flytjandi"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Höfundur"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Plata"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Staðsetning"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Streymisgerðir"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Óunnin stærð (bæti)"</string>
+</resources>
diff --git a/res/values-is/mimes.xml b/res/values-is/mimes.xml
new file mode 100644
index 0000000..b21d293
--- /dev/null
+++ b/res/values-is/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> skrá"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Skrá"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Mynd"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> mynd"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Hljóð"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> hljóð"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Myndskeið"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> myndskeið"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> geymsla"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android forrit"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Hreinn texti"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-skjal"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-skjal"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-skjal"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-kynning"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-töflureiknir"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google skjal"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google töflureiknir"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google kynning"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google teikning"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google tafla"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google eyðublað"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google kort"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google vefsvæði"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mappa"</string>
+</resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 1a3cce8..b5be412 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Þjappa"</string>
<string name="menu_extract" msgid="8171946945982532262">"Flytja út í…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Endurnefna"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Eiginleikar"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Sækja upplýsingar"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Opna í <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nýr gluggi"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Klippa"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Færa"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Hunsa"</string>
<string name="button_retry" msgid="4011461781916631389">"Reyna aftur"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Hreinsa"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Sýna í þjónustu"</string>
<string name="not_sorted" msgid="7813496644889115530">"Ekki flokkuð"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Heiti"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Samantekt"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Gerð"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Stærð"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Breytt"</string>
- <string name="directory_children" msgid="8115290268549503262">"Fjöldi barna"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Fjöldi atriða"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Hækkandi"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Lækkandi"</string>
<string name="drawer_open" msgid="8071673398187261741">"Sýna rótarsöfn"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Ekki hægt að opna skrá"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Ekki er hægt að opna skrár í geymslu"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Ekki hægt að eyða einhverjum skjölum"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Ekki tókst að sækja eiginleika"</string>
<string name="share_via" msgid="8725082736005677161">"Deila í gegnum"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Afritar skrár"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Þjappar skrám"</string>
diff --git a/res/values-it/inspector_strings.xml b/res/values-it/inspector_strings.xml
new file mode 100644
index 0000000..fcc7c83
--- /dev/null
+++ b/res/values-it/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informazioni"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Impossibile caricare le informazioni del file"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informazioni di debug (solo sviluppatori)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadati non elaborati: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Dettagli contenuti multimediali"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Questo tipo di file viene aperto con"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Questo file è fornito da"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Non selezionata"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Sconosciuto"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensioni"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordinate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitudine"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Fotocamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Apertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocità otturatore"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Durata"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Data/ora"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Lunghezza focale"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO equivalenti"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositore"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Geolocalizzazione"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipi di stream"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Dimensioni file non elaborato (byte)"</string>
+</resources>
diff --git a/res/values-it/mimes.xml b/res/values-it/mimes.xml
new file mode 100644
index 0000000..cffc59c
--- /dev/null
+++ b/res/values-it/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"File <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Immagine"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Immagine <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archivio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Applicazione Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Solo testo"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Documento HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Documento PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Documento Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Presentazione PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Foglio di calcolo Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Documento Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Foglio di lavoro Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Presentazione Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Disegno Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabella Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Modulo Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mappa Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Sito Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Cartella"</string>
+</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 8f6403e..fcf7baa 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimi"</string>
<string name="menu_extract" msgid="8171946945982532262">"Estrai in…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Rinomina"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Proprietà"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Informazioni"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Visualizza in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nuova finestra"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Taglia"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Sposta"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ignora"</string>
<string name="button_retry" msgid="4011461781916631389">"Riprova"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Cancella"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostra in provider"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nessun ordine"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nome"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Riepilogo"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Dimensioni"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Ultima modifica"</string>
- <string name="directory_children" msgid="8115290268549503262">"Numero di figli"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Numero di elementi"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Crescente"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Decrescente"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostra nodi principali"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Impossibile aprire il file."</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Impossibile aprire i file negli archivi"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Impossibile eliminare alcuni documenti."</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Impossibile caricare le proprietà"</string>
<string name="share_via" msgid="8725082736005677161">"Condividi tramite"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copia dei file in corso"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compressione di file"</string>
diff --git a/res/values-iw/inspector_strings.xml b/res/values-iw/inspector_strings.xml
new file mode 100644
index 0000000..e47dd80
--- /dev/null
+++ b/res/values-iw/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"מאפיינים"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"לא ניתן היה לטעון את פרטי הקובץ"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"מידע על ניפוי באגים (פיתוח בלבד)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"סוג המטא נתונים של קובץ ה-RAW: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"פרטי הקבצים"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"אפשר לפתוח קבצים מהסוג הזה באמצעות"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"הקובץ סופק על ידי"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"לא נבחרה"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"לא ידועה"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"מידות"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"קואורדינטות"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"גובה"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"מצלמה"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"צמצם"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"מהירות תריס"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"משך"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"צולם ב-"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"אורך מוקד"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> מ\"מ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"רגישות לאור (שווה ערך ל-ISO)"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"אמן"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"מלחין"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"אלבום"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"מיקום"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Stream types"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"גודל קובץ RAW (בייט)"</string>
+</resources>
diff --git a/res/values-iw/mimes.xml b/res/values-iw/mimes.xml
new file mode 100644
index 0000000..b871900
--- /dev/null
+++ b/res/values-iw/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"קובץ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"קובץ"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"תמונה"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"תמונה בפורמט <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"אודיו"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"אודיו בפורמט <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"וידאו"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"קובץ וידאו בפורמט <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"קובץ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"אפליקציית Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"טקסט פשוט"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"מסמך HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"קובץ PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"מסמך Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"מצגת PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"גיליון אלקטרוני ב-Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"מסמך ב-Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"גיליון אלקטרוני ב-Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"מצגת ב-Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"שרטוט ב-Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"טבלה ב-Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"טופס ב-Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"מפה ב-Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"אתר ב-Google Sites"</string>
+ <string name="directory_type" msgid="2702987727566226354">"תיקיה"</string>
+</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 0ea688e..7a45d7f 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -27,21 +27,21 @@
<string name="menu_create_dir" msgid="2413624798689091042">"תיקיה חדשה"</string>
<string name="menu_grid" msgid="1453636521731880680">"תצוגת רשת"</string>
<string name="menu_list" msgid="6714267452146410402">"תצוגת רשימה"</string>
- <string name="menu_search" msgid="1876699106790719849">"חפש"</string>
+ <string name="menu_search" msgid="1876699106790719849">"חיפוש"</string>
<string name="menu_settings" msgid="6520844520117939047">"הגדרות אחסון"</string>
<string name="menu_open" msgid="9092138100049759315">"פתח"</string>
<string name="menu_open_with" msgid="5507647065467520229">"פתיחה באמצעות"</string>
<string name="menu_open_in_new_window" msgid="6686563636123311276">"פתיחה בחלון חדש"</string>
- <string name="menu_save" msgid="5195367497138965168">"שמור"</string>
+ <string name="menu_save" msgid="5195367497138965168">"שמירה"</string>
<string name="menu_share" msgid="4307140947108068356">"שתף"</string>
- <string name="menu_delete" msgid="1022254131543256626">"מחק"</string>
+ <string name="menu_delete" msgid="1022254131543256626">"מחיקה"</string>
<string name="menu_select_all" msgid="7600576812185570403">"בחר הכל"</string>
<string name="menu_copy" msgid="7404820171352314754">"העתק אל…"</string>
<string name="menu_move" msgid="2310760789561129882">"העבר אל…"</string>
<string name="menu_compress" msgid="37539111904724188">"דחוס"</string>
<string name="menu_extract" msgid="8171946945982532262">"חלץ לתיקייה…"</string>
<string name="menu_rename" msgid="1883113442688817554">"שנה שם"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"מאפיינים"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"מידע על המסמך"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"הצג ב-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"חלון חדש"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"גזור"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"העבר"</string>
<string name="button_dismiss" msgid="7235249361023803349">"ביטול"</string>
<string name="button_retry" msgid="4011461781916631389">"נסה שנית"</string>
+ <string name="button_clear" msgid="5412304437764369441">"ניקוי"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"הצג באפליקציה של הספק"</string>
<string name="not_sorted" msgid="7813496644889115530">"לא ממוין"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"שם"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"סיכום"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"סוג"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"גודל"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"שינוי אחרון"</string>
- <string name="directory_children" msgid="8115290268549503262">"מספר הבנים"</string>
+ <string name="directory_items" msgid="6645621978998614003">"מספר הפריטים"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"סדר עולה"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"סדר יורד"</string>
<string name="drawer_open" msgid="8071673398187261741">"הצג שורשים"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"לא ניתן לפתוח את הקובץ"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"לא ניתן לפתוח קבצים בארכיונים"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"לא ניתן למחוק חלק מהמסמכים"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"לא ניתן היה לטעון מאפיינים"</string>
<string name="share_via" msgid="8725082736005677161">"שתף באמצעות"</string>
<string name="copy_notification_title" msgid="52256435625098456">"מעתיק קבצים"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"דוחס קבצים"</string>
diff --git a/res/values-ja/inspector_strings.xml b/res/values-ja/inspector_strings.xml
new file mode 100644
index 0000000..eb9737a
--- /dev/null
+++ b/res/values-ja/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"情報"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ファイル情報を読み込めませんでした"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"デバッグ情報(デベロッパーのみ)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"未加工のメタデータ: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"メディアの詳細"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"このファイル形式を開けるアプリ"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"このファイルの提供元"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"未選択"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"不明"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"サイズ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"座標"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"高度"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"カメラ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"絞り"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"シャッター スピード"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"時間"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"撮影"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"レンズ焦点距離"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO 相当"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"アーティスト"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"作曲者"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"アルバム"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"場所"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ストリーム タイプ"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"未加工のサイズ(バイト)"</string>
+</resources>
diff --git a/res/values-ja/mimes.xml b/res/values-ja/mimes.xml
new file mode 100644
index 0000000..ce62382
--- /dev/null
+++ b/res/values-ja/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ファイル"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ファイル"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"画像"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> 画像"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"音声"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> 音声"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"動画"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> 動画"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> アーカイブ"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android アプリ"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"書式なしテキスト"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML ドキュメント"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ドキュメント"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ドキュメント"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint プレゼンテーション"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel スプレッドシート"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google ドキュメント"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google スプレッドシート"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google プレゼンテーション"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google 図形描画"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google Table"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google フォーム"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google マップ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google サイト"</string>
+ <string name="directory_type" msgid="2702987727566226354">"フォルダ"</string>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index fc101fb..c06bf9b 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"圧縮"</string>
<string name="menu_extract" msgid="8171946945982532262">"次の場所に解凍…"</string>
<string name="menu_rename" msgid="1883113442688817554">"名前を変更"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"プロパティ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"情報を見る"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g>に表示"</string>
<string name="menu_new_window" msgid="2947837751796109126">"新しいウィンドウ"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"切り取り"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"移動"</string>
<string name="button_dismiss" msgid="7235249361023803349">"非表示"</string>
<string name="button_retry" msgid="4011461781916631389">"再試行"</string>
+ <string name="button_clear" msgid="5412304437764369441">"削除"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"プロバイダで表示"</string>
<string name="not_sorted" msgid="7813496644889115530">"並べ替えなし"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"名前"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"概要"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"タイプ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"サイズ"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"最終変更"</string>
- <string name="directory_children" msgid="8115290268549503262">"子供の数"</string>
+ <string name="directory_items" msgid="6645621978998614003">"アイテム数"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"昇順"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"降順"</string>
<string name="drawer_open" msgid="8071673398187261741">"ルートを表示する"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ファイルを開けません"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"アーカイブ内のファイルを開くことはできません"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"一部のドキュメントを削除できません"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"プロパティを読み込めませんでした"</string>
<string name="share_via" msgid="8725082736005677161">"共有ツール"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ファイルのコピー中"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ファイルの圧縮中"</string>
diff --git a/res/values-ka/inspector_strings.xml b/res/values-ka/inspector_strings.xml
new file mode 100644
index 0000000..bb3cab1
--- /dev/null
+++ b/res/values-ka/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"ინფორმაცია"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ფაილის ინფორმაციის ჩატვირთვა ვერ მოხერხდა"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"შეცდომების გამართვის ინფორმაცია (მხოლოდ დეველ.)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"ნედლი მეტა-მონაცემები: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"მედიის დეტალები"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ამ ტიპის ფაილი იხსნება"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ფაილის მომწოდებელი:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"არ არის არჩეული"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"უცნობი"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ზომები"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> — <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>მეგაპიქსელი"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"კოორდინატები"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"სიმაღლე"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"კამერა"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g>, <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"აპერტურა"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ობიექტივის საკეტის სისწრაფე"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"ხანგრძლივობა"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"გადაღებულია:"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ფოკუსური მანძილი"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>მმ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-ს ეკვივალენტი"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO: <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"შემსრულებელი"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"კომპოზიტორი"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ალბომი"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"მდებარეობა"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"სტრიმინგის ტიპები"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"ნედლი ზომა (ბაიტები)"</string>
+</resources>
diff --git a/res/values-ka/mimes.xml b/res/values-ka/mimes.xml
new file mode 100644
index 0000000..8264d81
--- /dev/null
+++ b/res/values-ka/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ფაილი"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ფაილი"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"სურათი"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> სურათი"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"აუდიო"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> აუდიო"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ვიდეო"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> ვიდეო"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> არქივი"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-ის აპლიკაცია"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"ჩვეულებრივი ტექსტი"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML დოკუმენტი"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF დოკუმენტი"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word დოკუმენტი"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint პრეზენტაცია"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-ის ელცხრილი"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google დოკუმენტი"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google ელცხრილი"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google პრეზენტაცია"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ნახაზი"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google ცხრილი"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ფორმა"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google რუკა"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google საიტი"</string>
+ <string name="directory_type" msgid="2702987727566226354">"საქაღალდე"</string>
+</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 506d232..4868fc5 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"შეკუმშვა"</string>
<string name="menu_extract" msgid="8171946945982532262">"ამოღება…"</string>
<string name="menu_rename" msgid="1883113442688817554">"გადარქმევა"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"მახასიათებლები"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"ინფორმაციის მიღება"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g>-ში ნახვა"</string>
<string name="menu_new_window" msgid="2947837751796109126">"ახალი ფანჯარა"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"ამოჭრა"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"გადაადგილება"</string>
<string name="button_dismiss" msgid="7235249361023803349">"უარყოფა"</string>
<string name="button_retry" msgid="4011461781916631389">"ხელახლა ცდა"</string>
+ <string name="button_clear" msgid="5412304437764369441">"გასუფთავება"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"პროვაიდერში ჩვენება"</string>
<string name="not_sorted" msgid="7813496644889115530">"დაულაგებელი"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"სახელი"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"რეზიუმე"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ტიპი"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"ზომა"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"ცვლილება"</string>
- <string name="directory_children" msgid="8115290268549503262">"ბავშვთა რაოდენობა"</string>
+ <string name="directory_items" msgid="6645621978998614003">"ერთეულების რაოდენობა"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ზრდადი"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"კლებადი"</string>
<string name="drawer_open" msgid="8071673398187261741">"ფესვების ჩვენება"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ფაილის გახსნა ვერ ხერხდება"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"არქივებში განთავსებული ფაილების გახსნა ვერ მოხერხდა"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"ზოგიერთი დოკუმენტის წაშლა ვერ ხერხდება"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"მახასიათებლების ჩატვირთვა ვერ მოხერხდა"</string>
<string name="share_via" msgid="8725082736005677161">"გაზიარება…"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ფაილების კოპირება…"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"მიმდინარეობს ფაილების შეკუმშვა"</string>
diff --git a/res/values-kk/inspector_strings.xml b/res/values-kk/inspector_strings.xml
new file mode 100644
index 0000000..88991f3
--- /dev/null
+++ b/res/values-kk/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Ақпарат"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Файл ақпараты жүктелмеді"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Түзету туралы ақпарат (тек әзірлеуші)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"RAW метадеректері: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Медиамазмұн деректері"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Мұндай файл түрі келесі қолданбамен ашылады"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Файлды ұсынушы"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Таңдалмады"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Белгісіз"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Өлшемдер"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> МП"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координаталар"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Биіктік"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aпертура"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Ысырма жылдамдығы"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Ұзақтығы"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Түсірілді"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Фокус қашықтығы"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> мм"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO баламасы"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO жылдамдығы: <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Орындаушы"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Композитор"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Альбом"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Орын"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Трансляция түрлері"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"RAW файлының өлшемі (байт)"</string>
+</resources>
diff --git a/res/values-kk/mimes.xml b/res/values-kk/mimes.xml
new file mode 100644
index 0000000..166d2ed
--- /dev/null
+++ b/res/values-kk/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> файлы"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Файл"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Сурет"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> суреті"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Aудио"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> аудиофайлы"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Бейне"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> бейнефайлы"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> мұрағаты"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android қолданбасы"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Қарапайым мәтін"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML құжаты"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF құжаты"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word құжаты"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint көрсетілімі"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel электрондық кестесі"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google құжаты"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google электрондық кестесі"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google көрсетілімі"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google суреті"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google кестесі"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google үлгісі"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google картасы"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google сайты"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Қалта"</string>
+</resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index b466594..00a6a72 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Сығу"</string>
<string name="menu_extract" msgid="8171946945982532262">"Алынуда…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Атауын өзгерту"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Сипаттары"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Ақпарат алу"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> ішінде көру"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Жаңа терезе"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Қиып алу"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Тасымалдау"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Жабу"</string>
<string name="button_retry" msgid="4011461781916631389">"Әрекетті қайталау"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Өшіру"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Провайдерде көрсету"</string>
<string name="not_sorted" msgid="7813496644889115530">"Сұрыпталмаған"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Аты"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Жиынтық мәлімет"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tүрі"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Көлемі"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Өзгертілген уақыты"</string>
- <string name="directory_children" msgid="8115290268549503262">"Балалар саны"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Элементтер саны"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Арту ретімен"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Кему ретімен"</string>
<string name="drawer_open" msgid="8071673398187261741">"Түбір қалтаны көрсету"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Файл ашылмады"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Мұрағаттағы файлдар ашылмайды"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Кейбір құжаттар жойылмады"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Сипаттар жүктелмеді"</string>
<string name="share_via" msgid="8725082736005677161">"Бөлісу әдісі"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Файлдар көшірілуде"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Файлдар сығу"</string>
@@ -110,7 +111,7 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файл жойылуда.</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файл жойылуда.</item>
</plurals>
- <string name="undo" msgid="2902438994196400565">"Кері қайтару"</string>
+ <string name="undo" msgid="2902438994196400565">"Қайтару"</string>
<string name="copy_preparing" msgid="5326063807006898223">"Көшіруге дайындау…"</string>
<string name="compress_preparing" msgid="6650018601382062672">"Сығуға дайындалуда…"</string>
<string name="extract_preparing" msgid="58266275455027829">"Шығарып алуға дайындалуда…"</string>
diff --git a/res/values-km/inspector_strings.xml b/res/values-km/inspector_strings.xml
new file mode 100644
index 0000000..a199a86
--- /dev/null
+++ b/res/values-km/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"ព័ត៌មាន"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"មិនអាចផ្ទុកព័ត៌មានឯកសារបានទេ"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ព័ត៌មានអំពីការជួសជុល (dev ប៉ុណ្ណោះ)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"ទិន្នន័យមេតាដើម៖ <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"ព័ត៌មានលម្អិតអំពីមេឌៀ"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ប្រភេទឯកសារនេះបើកដោយប្រើ"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ឯកសារនេះត្រូវបានផ្ដល់ដោយ"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"មិនបានជ្រើសរើស"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"មិនស្គាល់"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ទំហំ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"កូអរដោណេ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"រយៈកម្ពស់"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"កាមេរ៉ា"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"ជម្រៅរូបភាព"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ល្បឿនពន្លឺរូបថត"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"រយៈពេល"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ថតនៅថ្ងៃទី"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ប្រវែងផ្ដោត"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ល្បឿន ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"សិល្បករ"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"អ្នកតាក់តែង"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"អាល់ប៊ុម"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"ទីកន្លែង"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ប្រភេទការផ្សាយ"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"ទំហំដើម (បៃ)"</string>
+</resources>
diff --git a/res/values-km/mimes.xml b/res/values-km/mimes.xml
new file mode 100644
index 0000000..3c16552
--- /dev/null
+++ b/res/values-km/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"ឯកសារ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ឯកសារ"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"រូបភាព"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"រូបភាព <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"សំឡេង"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"សំឡេង <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"វីដេអូ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"វីដេអូ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"បណ្ណសារ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"កម្មវិធី Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"អត្ថបទធម្មតា"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"ឯកសារ HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"ឯកសារ PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"ឯកសារ Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"បទបង្ហាញ PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"បញ្ជី Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google ឯកសារ"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"បញ្ជី Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google បទបង្ហាញ"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google គំនូរ"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google តារាង"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ទម្រង់បែបបទ"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google ផែនទី"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"ទំព័រ Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ថត"</string>
+</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 046f1e5..137b870 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"បង្ហាប់"</string>
<string name="menu_extract" msgid="8171946945982532262">"ស្រង់ទៅ…"</string>
<string name="menu_rename" msgid="1883113442688817554">"ប្ដូរឈ្មោះ"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"លក្ខណៈសម្បត្តិ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"ទទួលព័ត៌មាន"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"មើលនៅក្នុង <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"ផ្ទាំងវិនដូថ្មី"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"កាត់"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ផ្លាស់ទី"</string>
<string name="button_dismiss" msgid="7235249361023803349">"បដិសេធ"</string>
<string name="button_retry" msgid="4011461781916631389">"ព្យាយាមម្តងទៀត"</string>
+ <string name="button_clear" msgid="5412304437764369441">"សម្អាត"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"បង្ហាញនៅក្នុងក្រុមហ៊ុនផ្តល់សេវា"</string>
<string name="not_sorted" msgid="7813496644889115530">"Not sorted"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"ឈ្មោះ"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"សេចក្តីសង្ខេប"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ប្រភេទ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"ទំហំ"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"បានកែសម្រួល"</string>
- <string name="directory_children" msgid="8115290268549503262">"ចំនួនកុមារ"</string>
+ <string name="directory_items" msgid="6645621978998614003">"ចំនួនធាតុ"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ឡើង"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"ចុះ"</string>
<string name="drawer_open" msgid="8071673398187261741">"បង្ហាញ roots"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"មិនអាចបើកឯកសារបានទេ"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"មិនអាចបើកឯកសារនៅក្នុងបណ្ណសារបានទេ"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"មិនអាចលុបឯកសារមួយចំនួន"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"មិនអាចផ្ទុកលក្ខណសម្បត្តិបានទេ"</string>
<string name="share_via" msgid="8725082736005677161">"ចែករំលែកតាម"</string>
<string name="copy_notification_title" msgid="52256435625098456">"កំពុងចម្លងឯកសារ"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"កំពុងបង្ហាប់ឯកសារ"</string>
diff --git a/res/values-kn/inspector_strings.xml b/res/values-kn/inspector_strings.xml
new file mode 100644
index 0000000..29481bb
--- /dev/null
+++ b/res/values-kn/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"ಮಾಹಿತಿ"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ಫೈಲ್ ಮಾಹಿತಿಯನ್ನು ಲೋಡ್ ಮಾಡಲಾಗಲಿಲ್ಲ"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ಡೀಬಗ್ ಮಾಹಿತಿ (dev ಮಾತ್ರ)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw ಮೆಟಾಡೇಟಾ: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"ಮಾಧ್ಯಮ ವಿವರಗಳು"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ಈ ಪ್ರಕಾರದ ಫೈಲ್ ಇದರ ಮೂಲಕ ತೆರೆಯುತ್ತದೆ"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ಈ ಫೈಲ್ ಅನ್ನು ವಿತರಿಸಿದವರು"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"ಆಯ್ಕೆಮಾಡಲಾಗಿಲ್ಲ"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"ಅಪರಿಚಿತ"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ಅಳತೆಗಳು"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>ಎಮ್ಪಿ"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"ಅಕ್ಷಾಂಶಗಳು"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ಎತ್ತರ"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"ಕ್ಯಾಮರಾ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"ಅಪರ್ಚರ್"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ಶಟರ್ ವೇಗ"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"ಅವಧಿ"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ತೆಗೆದುಕೊಂಡಾಗ"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ಫೋಕಲ್ ಅಂತರ"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>ಮಿಮೀ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ಸಮಾನ"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"ಕಲಾವಿದರು"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"ಸಂಯೋಜಕ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ಆಲ್ಬಮ್"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"ಸ್ಥಳ"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ಸ್ಟ್ರೀಮ್ ವಿಧಗಳು"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"RAW ಗಾತ್ರ (ಬೈಟ್ಗಳು)"</string>
+</resources>
diff --git a/res/values-kn/mimes.xml b/res/values-kn/mimes.xml
new file mode 100644
index 0000000..515c423
--- /dev/null
+++ b/res/values-kn/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ಫೈಲ್"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ಫೈಲ್"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"ಚಿತ್ರ"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> ಚಿತ್ರ"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ಆಡಿಯೋ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ಆಡಿಯೋ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ವೀಡಿಯೊ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> ವೀಡಿಯೊ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> ಆರ್ಕೈವ್ ಮಾಡಿ"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android ಅಪ್ಲಿಕೇಶನ್"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"ಸರಳ ಪಠ್ಯ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML ಡಾಕ್ಯುಮೆಂಟ್"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ಡಾಕ್ಯುಮೆಂಟ್"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ಡಾಕ್ಯುಮೆಂಟ್"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint ಪ್ರಸ್ತುತಿ"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel ಸ್ಪ್ರೆಡ್ಶೀಟ್"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google ಡಾಕ್ಯುಮೆಂಟ್"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google ಸ್ಪ್ರೆಡ್ಶೀಟ್"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google ಪ್ರಸ್ತುತಿ"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ರೇಖಾಚಿತ್ರ"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google ಟೇಬಲ್"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ಫಾರ್ಮ್"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google ನಕ್ಷೆ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google ಸೈಟ್"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ಫೋಲ್ಡರ್"</string>
+</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index a199277..920af9d 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"ಕುಗ್ಗಿಸಿ"</string>
<string name="menu_extract" msgid="8171946945982532262">"ಇದಕ್ಕೆ ಬೇರ್ಪಡಿಸಲಾಗಿದೆ…"</string>
<string name="menu_rename" msgid="1883113442688817554">"ಮರುಹೆಸರಿಸು"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"ಗುಣಲಕ್ಷಣಗಳು"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಿರಿ"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> ನಲ್ಲಿ ವೀಕ್ಷಿಸಿ"</string>
<string name="menu_new_window" msgid="2947837751796109126">"ಹೊಸ ವಿಂಡೋ"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"ಕತ್ತರಿಸು"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ಸರಿಸು"</string>
<string name="button_dismiss" msgid="7235249361023803349">"ವಜಾಗೊಳಿಸಿ"</string>
<string name="button_retry" msgid="4011461781916631389">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
+ <string name="button_clear" msgid="5412304437764369441">"ತೆರವುಗೊಳಿಸಿ"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"ಒದಗಿಸುವವರಲ್ಲಿ ತೋರಿಸಿ"</string>
<string name="not_sorted" msgid="7813496644889115530">"ವಿಂಗಡಿಸಲಾಗಿಲ್ಲ"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"ಹೆಸರು"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"ಸಾರಾಂಶ"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ಪ್ರಕಾರ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"ಗಾತ್ರ"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"ಮಾರ್ಪಾಡು"</string>
- <string name="directory_children" msgid="8115290268549503262">"ಮಕ್ಕಳ ಸಂಖ್ಯೆ"</string>
+ <string name="directory_items" msgid="6645621978998614003">"ಐಟಂಗಳ ಸಂಖ್ಯೆ"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ಆರೋಹಣ"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"ಅವರೋಹಣ"</string>
<string name="drawer_open" msgid="8071673398187261741">"ರೂಟ್ಗಳನ್ನು ತೋರಿಸು"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ಫೈಲ್ ತೆರೆಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"ಆರ್ಕೈವ್ಗಳಲ್ಲಿ ಫೈಲ್ಗಳನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"ಕೆಲವು ಡಾಕ್ಯುಮೆಂಟ್ಗಳನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"ಗುಣಲಕ್ಷಣಗಳನ್ನು ಲೋಡ್ ಮಾಡುವುದು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="share_via" msgid="8725082736005677161">"ಈ ಮೂಲಕ ಹಂಚಿಕೊಳ್ಳಿ"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ಫೈಲ್ಗಳನ್ನು ನಕಲಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ಫೈಲ್ ಕುಗ್ಗಿಸಲಾಗುತ್ತಿದೆ"</string>
@@ -166,7 +167,7 @@
<string name="file_operation_rejected" msgid="4301554203329008794">"ಫೈಲ್ ಕಾರ್ಯಾಚರಣೆಗೆ ಬೆಂಬಲವಿಲ್ಲ."</string>
<string name="file_operation_error" msgid="2234357335716533795">"ಫೈಲ್ ಕಾರ್ಯಾಚರಣೆ ವಿಫಲವಾಗಿದೆ."</string>
<string name="rename_error" msgid="6700093173508118635">"ಡಾಕ್ಯುಮೆಂಟ್ ಮರುಹೆಸರಿಸಲು ವಿಫಲವಾಗಿದೆ"</string>
- <string name="menu_eject_root" msgid="9215040039374893613">"ಎಜೆಕ್ಟ್"</string>
+ <string name="menu_eject_root" msgid="9215040039374893613">"ಇಜೆಕ್ಟ್"</string>
<string name="notification_copy_files_converted_title" msgid="6916768494891833365">"ಕೆಲವು ಫೈಲ್ಗಳನ್ನು ಪರಿವರ್ತಿಸಲಾಗಿದೆ"</string>
<string name="open_external_dialog_request" msgid="8173558471322861268">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> ರಲ್ಲಿ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ಡೈರೆಕ್ಟರಿಗೆ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ಪ್ರವೇಶ ನೀಡುವುದೇ?"</string>
<string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ಡೈರೆಕ್ಟರಿಗೆ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ಗೆ ಪ್ರವೇಶ ನೀಡುವುದೇ?"</string>
diff --git a/res/values-ko/inspector_strings.xml b/res/values-ko/inspector_strings.xml
new file mode 100644
index 0000000..97acd80
--- /dev/null
+++ b/res/values-ko/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"정보"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"파일 정보를 로드할 수 없습니다"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"디버그 정보(개발자 전용)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"원본 메타데이터: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"미디어 세부정보"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"이 유형의 파일에 연결된 앱"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"파일 제공자:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"선택되지 않음"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"알 수 없음"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"크기"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g>x<xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"좌표"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"고도"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"카메라"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"조리개"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"셔터 속도"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"시간"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"촬영 일시"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"초점 거리"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO 등급"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"아티스트"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"작곡가"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"앨범"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"위치"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"스트림 유형"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"원본 크기(바이트)"</string>
+</resources>
diff --git a/res/values-ko/mimes.xml b/res/values-ko/mimes.xml
new file mode 100644
index 0000000..769d97a
--- /dev/null
+++ b/res/values-ko/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> 파일"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"파일"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"이미지"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> 이미지"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"오디오"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> 오디오"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"동영상"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> 동영상"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> 보관 파일"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android 애플리케이션"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"일반 텍스트"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML 문서"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF 문서"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word 문서"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint 프레젠테이션"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel 스프레드시트"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google 문서"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google 스프레드시트"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google 프레젠테이션"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google 드로잉"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google 표"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google 설문지"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google 지도"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google 사이트"</string>
+ <string name="directory_type" msgid="2702987727566226354">"폴더"</string>
+</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index d2e3084..d2072cd 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"압축"</string>
<string name="menu_extract" msgid="8171946945982532262">"다음 위치에 추출..."</string>
<string name="menu_rename" msgid="1883113442688817554">"이름 바꾸기"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"속성"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"정보 확인"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g>에서 보기"</string>
<string name="menu_new_window" msgid="2947837751796109126">"새 창"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"잘라내기"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"이동"</string>
<string name="button_dismiss" msgid="7235249361023803349">"닫기"</string>
<string name="button_retry" msgid="4011461781916631389">"다시 시도"</string>
+ <string name="button_clear" msgid="5412304437764369441">"삭제"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"제공업체 앱에서 보기"</string>
<string name="not_sorted" msgid="7813496644889115530">"정렬되지 않음"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"이름"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"요약"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"형식"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"크기"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"마지막 수정 시간"</string>
- <string name="directory_children" msgid="8115290268549503262">"자녀 수"</string>
+ <string name="directory_items" msgid="6645621978998614003">"항목 수"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"오름차순"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"내림차순"</string>
<string name="drawer_open" msgid="8071673398187261741">"루트 표시"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"파일을 열 수 없습니다."</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"보관 파일 안에 있는 파일은 열 수 없습니다."</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"일부 문서를 삭제할 수 없습니다."</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"속성을 로드할 수 없습니다."</string>
<string name="share_via" msgid="8725082736005677161">"공유에 사용할 앱"</string>
<string name="copy_notification_title" msgid="52256435625098456">"파일 복사"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"파일 압축 중"</string>
diff --git a/res/values-ky/inspector_strings.xml b/res/values-ky/inspector_strings.xml
new file mode 100644
index 0000000..a120911
--- /dev/null
+++ b/res/values-ky/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Маалымат"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Файл жөнүндө маалымат жүктөлбөй койду"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Мүчүлүштүктөрдү оңдоо маалыматы (түзм. гана)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Баштапкы метадата: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Медиа маалымат"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Файлдын мындай түрү төмөнкү колдонмо менен ачылат"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Бул файлды жасаган тутум"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Тандалган жок"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Белгисиз"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Чен-өлчөмү"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>Мпикс."</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координаталар"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Бийиктик"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Апертура"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Жапкычтын ылдамдыгы"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Узактыгы"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Тартылган күнү"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Фокустук аралык"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>мм"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO эквиваленти"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Аткаруучу"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Композитор"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Альбом"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Жайгашкан жер"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Агымдын түрү"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Баштапкы өлчөмү (байт)"</string>
+</resources>
diff --git a/res/values-ky/mimes.xml b/res/values-ky/mimes.xml
new file mode 100644
index 0000000..8eb7cd6
--- /dev/null
+++ b/res/values-ky/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> файлы"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Файл"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Сүрөт"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> сүрөтү"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аудио"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> форматындагы аудио файл"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Видео"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> видеосу"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> форматындагы архив"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android колдонмосу"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Жөнөкөй текст"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML документи"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF документи"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word документи"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint презентациясы"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel электрондук жадыбалы"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google документи"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google электрондук жадыбалы"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google презентациясы"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google чиймеси"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google жадыбалы"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google формасы"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google картасы"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google сайты"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Папка"</string>
+</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 5f98eaa..b92c8db 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Кысуу"</string>
<string name="menu_extract" msgid="8171946945982532262">"Төмөнкүгө чыгаруу…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Аталышын өзгөртүү"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Касиеттери"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Маалымат алуу"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> аркылуу көрүү"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Жаңы терезе"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Кесүү"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Жылдыруу"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Көз жаздымда калтыруу"</string>
<string name="button_retry" msgid="4011461781916631389">"Кайра аракет кылыңыз"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Тазалоо"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Демейки колдонмодон көрсөтүү"</string>
<string name="not_sorted" msgid="7813496644889115530">"Ылганган эмес"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Аты"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Жыйынтыгы"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Түрү"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Өлчөмү"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Өзгөрүлгөн"</string>
- <string name="directory_children" msgid="8115290268549503262">"Балдардын саны"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Элементтердин саны"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Чоңойгон ыраатта"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Кичирейген ыраатта"</string>
<string name="drawer_open" msgid="8071673398187261741">"Папкаларды көрсөтүү"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Файл ачылбай жатат"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Архивделген файлдарды ачуу мүмкүн эмес"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Кээ бир документтерди өчүрүү мүмкүн болбой жатат"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Касиеттери жүктөлбөй койду"</string>
<string name="share_via" msgid="8725082736005677161">"Бул аркылуу бөлүшүү"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Файлдар көчүрүлүүдө"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Файлдар кысылууда"</string>
diff --git a/res/values-lo/inspector_strings.xml b/res/values-lo/inspector_strings.xml
new file mode 100644
index 0000000..6d02420
--- /dev/null
+++ b/res/values-lo/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"ຂໍ້ມູນ"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ບໍ່ສາມາດໂຫຼດຂໍ້ມູນໄຟລ໌ໄດ້"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ຂໍ້ມູນດີບັກ (ນັກພັດທະນາເທົ່ານັ້ນ)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"ເມເຕເດຕາ Raw: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"ລາຍລະອຽດມີເດຍ"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ໄຟລ໌ປະເພດນີ້ເປີດດ້ວຍ"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ໄຟລ໌ນີ້ຖືກຈຳໜ່າຍໃຫ້ໂດຍ"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"ບໍ່ໄດ້ເລືອກ"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"ບໍ່ຮູ້ຈັກ"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ຂະໜາດພາບ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"ພິກັດ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ຄວາມສູງ"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"ກ້ອງຖ່າຍຮູບ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"ຮູຮັບແສງ"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ຄວາມໄວຊັດເຕີ"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"ໄລຍະເວລາ"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ຖ່າຍເມື່ອ"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ທາງຍາວໂຟກັສ"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ທຽບເທົ່າ"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"ສິນລະປິນ"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"ຜູ້ແຕ່ງ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ອະລະບໍ້າ"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"ສະຖານທີ່"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ປະເພດສະຕຣີມ"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"ຂະໜາດ Raw (ໄບຕ໌)"</string>
+</resources>
diff --git a/res/values-lo/mimes.xml b/res/values-lo/mimes.xml
new file mode 100644
index 0000000..55775c2
--- /dev/null
+++ b/res/values-lo/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"ໄຟລ໌ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ໄຟລ໌"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"ຮູບພາບ"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"ຮູບພາບ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ໄຟລ໌ສຽງ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"ໄຟລ໌ສຽງ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ວິດີໂອ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"ວິດີໂອ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"ແຟ້ມຈັດເກັບ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"ແອັບພລິເຄຊັນ Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"ຂໍ້ຄວາມທຳມະດາ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"ເອກະສານ HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"ເອກະສານ PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"ເອກະສານ Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"ພຣີເຊັນເທເຊິນ PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"ສະເປຣດຊີດ Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"ເອກະສານ Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"ສະເປຣດຊີດ Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"ພຣີເຊັນເທເຊິນ Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"ແບບແຕ້ມ Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"ຕາຕາລາງ Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"ແບບຟອມ Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"ແຜນທີ່ Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"ເວັບໄຊ Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ໂຟນເດີ"</string>
+</resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 1e53a8e..320075e 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"ບີບອັດ"</string>
<string name="menu_extract" msgid="8171946945982532262">"ແຕກໄຟລ໌ໄປ…"</string>
<string name="menu_rename" msgid="1883113442688817554">"ປ່ຽນຊື່"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"ຄຸນສົມບັດ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"ຂໍຂໍ້ມູນ"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"ເບິ່ງໃນ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"ໜ້າຈໍໃໝ່"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"ຕັດ"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ຍ້າຍ"</string>
<string name="button_dismiss" msgid="7235249361023803349">"ປິດໄວ້"</string>
<string name="button_retry" msgid="4011461781916631389">"ລອງໃໝ່ອີກເທື່ອໜຶ່ງ"</string>
+ <string name="button_clear" msgid="5412304437764369441">"ລຶບລ້າງ"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"ສະແດງໃນຜູ້ໃຫ້ບລິການ"</string>
<string name="not_sorted" msgid="7813496644889115530">"ບໍ່ໄດ້ຈັດຮຽງ"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"ຊື່"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"ສະຫຼຸບ"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ປະເພດ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"ຂະໜາດ"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"ແກ້ໄຂເມື່ອ"</string>
- <string name="directory_children" msgid="8115290268549503262">"ຈຳນວນຂອງລູກ"</string>
+ <string name="directory_items" msgid="6645621978998614003">"ຈໍານວນລາຍການ"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ໃຫຍ່ຫານ້ອຍ"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"ນ້ອຍຫາໃຫຍ່"</string>
<string name="drawer_open" msgid="8071673398187261741">"ສະແດງ roots"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ບໍ່ສາມາດເປີດໄຟລ໌ໄດ້"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"ບໍ່ສາມາດເປີດໄຟລ໌ໃນແຟ້ມຈັດເກັບໄດ້"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"ບໍ່ສາມາດລຶບບາງເອກະສານໄດ້"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"ບໍ່ສາມາດໂຫຼດຄຸນສົມບັດໄດ້"</string>
<string name="share_via" msgid="8725082736005677161">"ແບ່ງປັນຜ່ານ"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ກຳລັງສຳເນົາໄຟລ໌"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ກຳລັງບີບອັດໄຟລ໌"</string>
diff --git a/res/values-lt/inspector_strings.xml b/res/values-lt/inspector_strings.xml
new file mode 100644
index 0000000..20c28bb
--- /dev/null
+++ b/res/values-lt/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informacija"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Nepavyko įkelti failo"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Derinimo informacija (tik kūrėjams)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Neapdoroto failo metaduomenys: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Išsami medijos informacija"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Šio tipo failas atidaromas naudojant"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Šį failą teikia"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nepasirinkta"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Nežinoma"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Matmenys"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinatės"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Aukštis virš jūros lygio"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Fotoaparatas"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Diafragma"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Užrakto greitis"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Trukmė"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Nufotografuota"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Židinio nuotolis"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalentas"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Atlikėjas"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Kompozitorius"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albumas"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Vieta"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Srautų tipai"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Neapdoroto failo dydis (baitais)"</string>
+</resources>
diff --git a/res/values-lt/mimes.xml b/res/values-lt/mimes.xml
new file mode 100644
index 0000000..5bf01e2
--- /dev/null
+++ b/res/values-lt/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> failas"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Failas"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Vaizdas"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> vaizdas"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Garso įrašas"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> garso įrašas"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vaizdo įrašas"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> vaizdo įrašas"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> archyvas"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"„Android“ programa"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Grynasis tekstas"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML dokumentas"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF dokumentas"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"„Word“ dokumentas"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"„PowerPoint“ pristatymas"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"„Excel“ skaičiuoklė"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"„Google“ dokumentas"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"„Google“ skaičiuoklė"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"„Google“ pristatymas"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"„Google“ piešinys"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"„Google“ lentelė"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"„Google“ forma"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"„Google“ žemėlapis"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"„Google“ svetainė"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Aplankas"</string>
+</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 681b3df..ec80676 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Suglaudinti"</string>
<string name="menu_extract" msgid="8171946945982532262">"Išskleisti į..."</string>
<string name="menu_rename" msgid="1883113442688817554">"Pervardyti"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Ypatybės"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Gauti informacijos"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Žr. <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Naujas langas"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Iškirpti"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Perkelti"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Atsisakyti"</string>
<string name="button_retry" msgid="4011461781916631389">"Bandyti dar kartą"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Išvalyti"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Rodyti naudojant teikėjo programą"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nerūšiuota"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Pavadinimas"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Suvestinė"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipas"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Dydis"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Pakeista"</string>
- <string name="directory_children" msgid="8115290268549503262">"Antrinių elementų skaičius"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Elementų skaičius"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Didėjimo tvarka"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Mažėjimo tvarka"</string>
<string name="drawer_open" msgid="8071673398187261741">"Rodyti šaknis"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Nepavyksta atidaryti failo"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Negalima atidaryti failų archyvuose"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nepavyko ištrinti kai kurių dokumentų"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Nepavyko įkelti nuosavybių"</string>
<string name="share_via" msgid="8725082736005677161">"Bendrinti naudojant"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopijuojami failai"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Glaudinami failai"</string>
diff --git a/res/values-lv/inspector_strings.xml b/res/values-lv/inspector_strings.xml
new file mode 100644
index 0000000..739d519
--- /dev/null
+++ b/res/values-lv/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informācija"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Nevarēja ielādēt faila informāciju"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Atkļūdošanas informācija (tikai izstrādātājiem)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Neapstrādāti metadati: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Multivides informācija"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Šāda veida failu var atvērt lietotnē"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Šis fails ir nodrošināts lietotnē"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nav atlasīta"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Nezināma"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Izmēri"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> — <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinātas"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Augstums"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Diafragmas atvērums"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Slēdža ātrums"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Ilgums"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Uzņemts:"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Fokusa attālums"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalents"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Izpildītājs"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Komponists"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albums"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Atrašanās vieta"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Straumes veidi"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Neapstrādāta faila lielums (baiti)"</string>
+</resources>
diff --git a/res/values-lv/mimes.xml b/res/values-lv/mimes.xml
new file mode 100644
index 0000000..afe110b
--- /dev/null
+++ b/res/values-lv/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> fails"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fails"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Attēls"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> attēls"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> arhīvs"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android lietotne"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Vienkāršs teksts"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML dokuments"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF dokuments"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word dokuments"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint prezentācija"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel izklājlapa"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google dokuments"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google izklājlapa"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google prezentācija"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google zīmējums"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google tabula"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google veidlapa"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google karte"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google vietne"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mape"</string>
+</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 3672588..16e50a8 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Saspiest"</string>
<string name="menu_extract" msgid="8171946945982532262">"Izvilkt..."</string>
<string name="menu_rename" msgid="1883113442688817554">"Pārdēvēt"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Rekvizīti"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Iegūt informāciju"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Skatīt, izmantojot <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Jauns logs"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Izgriezt"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Pārvietot"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Nerādīt"</string>
<string name="button_retry" msgid="4011461781916631389">"Mēģināt vēlreiz"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Dzēst"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Rādīt nodrošinātājā"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nav kārtoti"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nosaukums"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Kopsavilkums"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Veids"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Lielums"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Izmaiņas"</string>
- <string name="directory_children" msgid="8115290268549503262">"Bērnu skaits"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Vienumu skaits"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Augošā secībā"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Dilstošā secībā"</string>
<string name="drawer_open" msgid="8071673398187261741">"Rādīt saknes"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Nevar atvērt failu."</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Nevar atvērt arhīvos esošos failus"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nevar izdzēst dažus dokumentus."</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Nevarēja ielādēt rekvizītus"</string>
<string name="share_via" msgid="8725082736005677161">"Kopīgošanas veids"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Failu kopēšana"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Failu saspiešana"</string>
diff --git a/res/values-mk/inspector_strings.xml b/res/values-mk/inspector_strings.xml
new file mode 100644
index 0000000..66cc7b6
--- /dev/null
+++ b/res/values-mk/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Информации"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Не можеше да се вчитаат информациите за датотеката"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Информации за отстранување грешки (само за DEV)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Необработени метаподатоци: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Детали за аудиовизуелните содржини"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Овој вид датотека се отвора со"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Датотекава е обезбедена од"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Не е избрана"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Непозната"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Димензии"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> х <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координати"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Надморска височина"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Апертура"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Брзина на блендата"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Времетраење"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Фотографирано на"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Фокусна должина"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> мм"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Еквивалент на ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Изведувач"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Композитор"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Албум"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Локација"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Типови пренос"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Големина на необработена (бајти)"</string>
+</resources>
diff --git a/res/values-mk/mimes.xml b/res/values-mk/mimes.xml
new file mode 100644
index 0000000..167ab2d
--- /dev/null
+++ b/res/values-mk/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> датотека"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Датотека"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Слика"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> слика"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аудио"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> аудио"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Видео"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> видео"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> архива"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Апликација за Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Обичен текст"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML документ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF документ"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word документ"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint презентација"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Таб. пресметка на Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Документ на Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Таб. пресметка на Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Презентација на Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Цртеж на Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Табела на Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Формулар на Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Карта на Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Сајт на Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Папка"</string>
+</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 97d5141..7322e73 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Компресирај"</string>
<string name="menu_extract" msgid="8171946945982532262">"Отпакувај во…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Преименувај"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Својства"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Добијте информации"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Прикажи во <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Нов прозорец"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Исечи"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Премести"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Отфрли"</string>
<string name="button_retry" msgid="4011461781916631389">"Обидете се повторно"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Исчисти"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Прикажи во услугата на операторот"</string>
<string name="not_sorted" msgid="7813496644889115530">"Неподредени"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Име"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Краток преглед"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Тип"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Големина"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Изменето"</string>
- <string name="directory_children" msgid="8115290268549503262">"Број на деца"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Број на ставки"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Растечко"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Опаѓачко"</string>
<string name="drawer_open" msgid="8071673398187261741">"Прикажи корени"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Датотеката не може да се отвори"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Не може да се отвораат датотеките во архивите"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Некои документи не може да се избришат"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Не можеше да се вчитаат својствата"</string>
<string name="share_via" msgid="8725082736005677161">"Споделете преку"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Се копираат датотеки"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Компримирање датотеки"</string>
diff --git a/res/values-ml/inspector_strings.xml b/res/values-ml/inspector_strings.xml
new file mode 100644
index 0000000..0537230
--- /dev/null
+++ b/res/values-ml/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"വിവരം"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ഫയൽ വിവരം ലോഡുചെയ്യാനായില്ല"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ഡീബഗ് വിവരങ്ങൾ (dev മാത്രം)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"റോ മെറ്റാഡാറ്റാ: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"മീഡിയ വിശദാംശങ്ങള്"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ഇത്തരത്തിലുള്ള ഫയലുകൾ തുറക്കുന്നു"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ഈ ഫയൽ വിതരണം ചെയ്യുന്നത്"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"തിരഞ്ഞെടുത്തില്ല"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"അറിയില്ല"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"തലങ്ങൾ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"കോർഡിനേറ്റുകൾ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ഉയരം"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"ക്യാമറ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"അപ്റേച്ചർ"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ഷട്ടര് വേഗത"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"ദൈര്ഘ്യം"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"എടുത്തത്"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ഫോക്കൽ ദൈർഘ്യം"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>മി.മീ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO തത്തുല്യം"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"ആർട്ടിസ്റ്റ്"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"കമ്പോസർ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ആല്ബം"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"ലൊക്കേഷൻ"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"സ്ട്രീം തരങ്ങൾ"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"റോ വലുപ്പം (ബൈറ്റുകൾ)"</string>
+</resources>
diff --git a/res/values-ml/mimes.xml b/res/values-ml/mimes.xml
new file mode 100644
index 0000000..a6cfb79
--- /dev/null
+++ b/res/values-ml/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ഫയൽ"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ഫയല്"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"ചിത്രം"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> ചിത്രം"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ഓഡിയോ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ഓഡിയോ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"വീഡിയോ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> വീഡിയോ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> ആർക്കൈവുചെയ്യുക"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android ആപ്പ്"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"പ്ലെയിന് ടെക്സ്റ്റ്"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML ഡോക്യുമെന്റ്"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ഡോക്യുമെന്റ്"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ഡോക്യുമെന്റ്"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint പ്രസന്റേഷൻ"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel സ്പ്രെഡ്ഷീറ്റ്"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google പ്രമാണം"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google സ്പ്രെഡ്ഷീറ്റ്"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google അവതരണം"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ഡ്രോയിംഗ്"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google പട്ടിക"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ഫോം"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google മാപ്പ്"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google സൈറ്റ്"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ഫോള്ഡര്"</string>
+</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index ebfbc6b..c7692e7 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"കംപ്രസ്സുചെയ്യുക"</string>
<string name="menu_extract" msgid="8171946945982532262">"എക്സ്ട്രാക്റ്റുചെയ്യുക…"</string>
<string name="menu_rename" msgid="1883113442688817554">"പേരുമാറ്റുക"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"പ്രോപ്പർട്ടികൾ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"വിവരങ്ങൾ സ്വന്തമാക്കൂ"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> എന്നതിൽ കാണുക"</string>
<string name="menu_new_window" msgid="2947837751796109126">"പുതിയ വിന്ഡോ"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"മുറിക്കുക"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"നീക്കുക"</string>
<string name="button_dismiss" msgid="7235249361023803349">"ഡിസ്മിസ് ചെയ്യുക"</string>
<string name="button_retry" msgid="4011461781916631389">"വീണ്ടും ശ്രമിക്കുക"</string>
+ <string name="button_clear" msgid="5412304437764369441">"മായ്ക്കുക"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"ദാതാവിൽ കാണിക്കുക"</string>
<string name="not_sorted" msgid="7813496644889115530">"അടുക്കിയിട്ടില്ല"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"പേര്"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"ചുരുക്കം"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"തരം"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"വലുപ്പം"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"പരിഷ്ക്കരിച്ചു"</string>
- <string name="directory_children" msgid="8115290268549503262">"കുട്ടികളുടെ എണ്ണം"</string>
+ <string name="directory_items" msgid="6645621978998614003">"ഇനങ്ങളുടെ എണ്ണം"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ആരോഹണം"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"അവരോഹണം"</string>
<string name="drawer_open" msgid="8071673398187261741">"റൂട്ടുകൾ ദൃശ്യമാക്കുക"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ഫയൽ തുറക്കാൻ കഴിയില്ല"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"ആർക്കൈവുകളിലെ ഫയലുകൾ തുറക്കാൻ കഴിയില്ല"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"ചില പ്രമാണങ്ങൾ ഇല്ലാതാക്കാനായില്ല"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"പ്രോപ്പർട്ടികൾ ലോഡുചെയ്യാനായില്ല"</string>
<string name="share_via" msgid="8725082736005677161">"ഇതുവഴി പങ്കിടുക"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ഫയലുകൾ പകർത്തുന്നു"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ഫയലുകൾ കംപ്രസ്സുചെയ്യുന്നു"</string>
@@ -134,7 +135,7 @@
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ഇനം ഇല്ലാതാക്കാനായില്ല</item>
</plurals>
<string name="notification_touch_for_details" msgid="2385563502445129570">"വിശദാംശങ്ങൾ കാണുന്നതിന് ടാപ്പുചെയ്യുക"</string>
- <string name="close" msgid="905969391788869975">"അടയ്ക്കുക"</string>
+ <string name="close" msgid="905969391788869975">"അവസാനിപ്പിക്കുക"</string>
<plurals name="copy_failure_alert_content" formatted="false" msgid="5570549471912990536">
<item quantity="other">ഈ ഫയലുകൾ പകർത്തപ്പെട്ടില്ല: <xliff:g id="LIST_1">%1$s</xliff:g></item>
<item quantity="one">ഈ ഫയൽ പകർത്തപ്പെട്ടില്ല: <xliff:g id="LIST_0">%1$s</xliff:g></item>
diff --git a/res/values-mn/inspector_strings.xml b/res/values-mn/inspector_strings.xml
new file mode 100644
index 0000000..a06af5a
--- /dev/null
+++ b/res/values-mn/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Мэдээлэл"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Файлын мэдээллийг ачааллаж чадсангүй"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Дебаг хийх мэдээлэл (зөвхөн хөгжүүлэгчид)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"RAW мета өгөгдөл: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Медианы дэлгэрэнгүй"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ийм төрлийн файлыг дараахаар нээдэг"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Энэ файлыг дараахаас хангасан"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Сонгоогүй"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Тодорхойгүй"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Хэмжээс"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координат"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Өндөр"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камер"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Өрц"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Зураг дарах хурд"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Хугацаа"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Авсан огноо"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Фокусын урт"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO дүйцэх"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Уран бүтээлч"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Хөгжмийн зохиолч"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Цомог"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Байршил"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Цацалтын төрөл"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"RAW-н хэмжээ (байт)"</string>
+</resources>
diff --git a/res/values-mn/mimes.xml b/res/values-mn/mimes.xml
new file mode 100644
index 0000000..fed9c98
--- /dev/null
+++ b/res/values-mn/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> файл"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Файл"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Зураг"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> зураг"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аудио"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> аудио"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Видео"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> видео"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> архив"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Андройд апп"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Энгийн бичвэр"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML документ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF документ"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word документ"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint үзүүлэн"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-н хүснэгт"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google документ"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google хүснэгт"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google үзүүлэн"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google зураглал"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google хүснэгт"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google маягт"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google газрын зураг"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google сайт"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Фолдер"</string>
+</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index d20cbee..3988b41 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Шахах"</string>
<string name="menu_extract" msgid="8171946945982532262">"Дараахад задлах…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Нэр өөрчлөх"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Шинж чанар"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Мэдээлэл авах"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g>-д харах"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Шинэ цонх"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Таслах"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Зөөх"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Хаах"</string>
<string name="button_retry" msgid="4011461781916631389">"Дахин оролдох"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Устгах"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Үйлчилгээ үзүүлэгчид харуулах"</string>
<string name="not_sorted" msgid="7813496644889115530">"Эрэмбэлээгүй"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Нэр"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Хураангуй"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Төрөл"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Хэмжээ"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Өөрчилсөн"</string>
- <string name="directory_children" msgid="8115290268549503262">"Хүүхдийн тоо"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Зүйлийн тоо"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Дээшилж буй"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Буурч буй"</string>
<string name="drawer_open" msgid="8071673398187261741">"Документын санг харуулах"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Файлыг нээх боломжгүй байна"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Архивын файлыг нээх боломжгүй"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Зарим документыг устгах боломжгүй"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Документын мэдээллийг ачааллаж чадсангүй"</string>
<string name="share_via" msgid="8725082736005677161">"Дараахаар хуваалцах"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Файлыг хуулж байна"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Файлыг шахаж байна"</string>
diff --git a/res/values-mr/inspector_strings.xml b/res/values-mr/inspector_strings.xml
new file mode 100644
index 0000000..d933b56
--- /dev/null
+++ b/res/values-mr/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"माहिती"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"फाइलची माहिती लोड करता आली नाही"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"डीबग माहिती (फक्त डेव्हलपरसाठी)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"अविश्लेषित मेटाडेटा: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"मीडिया तपशील"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"या प्रकारची फाइल ज्याने उघडेल ते"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"कडून ही फाइल पुरवण्यात आली"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"निवडलेले नाही"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"अज्ञात"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"आकारमान"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"अक्षांश रेखांश"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"उंची"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"कॅमेरा"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"अॅपर्चर"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"शटर गती"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"कालावधी"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"रोजी घेतला"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"केंद्रावरून लांबी"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>मिमी"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO सारखे"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"कलाकार"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"रचनाकार"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"अल्बम"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"स्थान"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"स्ट्रीम प्रकार"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"रॉ आकार (बाइट)"</string>
+</resources>
diff --git a/res/values-mr/mimes.xml b/res/values-mr/mimes.xml
new file mode 100644
index 0000000..0429515
--- /dev/null
+++ b/res/values-mr/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> फाइल"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"फाइल"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"इमेज"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> इमेज"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ऑडिओ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ऑडिओ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"व्हिडिओ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> व्हिडिओ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> संग्रहित करा"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android अॅप्लिकेशन"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"साधा मजकूर"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML दस्तऐवज"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"पीडीएफ दस्तऐवज"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word दस्तऐवज"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint सादरीकरण"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel स्प्रेडशीट"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google दस्तऐवज"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google स्प्रेडशीट"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google सादरीकरण"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google रेखांकन"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google सारणी"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google फॉर्म"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google नकाशा"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google साइट"</string>
+ <string name="directory_type" msgid="2702987727566226354">"फोल्डर"</string>
+</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 5827eb9..81899f5 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -23,7 +23,7 @@
<!-- no translation found for launcher_label (799410258349837668) -->
<skip />
<string name="title_open" msgid="3165686459158020921">"वरून उघडा"</string>
- <string name="title_save" msgid="4384490653102710025">"येथे जतन करा"</string>
+ <string name="title_save" msgid="4384490653102710025">"येथे सेव्ह करा"</string>
<string name="menu_create_dir" msgid="2413624798689091042">"नवीन फोल्डर"</string>
<string name="menu_grid" msgid="1453636521731880680">"ग्रिड दृश्य"</string>
<string name="menu_list" msgid="6714267452146410402">"सूची"</string>
@@ -32,7 +32,7 @@
<string name="menu_open" msgid="9092138100049759315">"उघडा"</string>
<string name="menu_open_with" msgid="5507647065467520229">"यासह उघडा"</string>
<string name="menu_open_in_new_window" msgid="6686563636123311276">"नवीन विंडोमध्ये उघडा"</string>
- <string name="menu_save" msgid="5195367497138965168">"जतन करा"</string>
+ <string name="menu_save" msgid="5195367497138965168">"सेव्ह करा"</string>
<string name="menu_share" msgid="4307140947108068356">"सामायिक करा"</string>
<string name="menu_delete" msgid="1022254131543256626">"हटवा"</string>
<string name="menu_select_all" msgid="7600576812185570403">"सर्व निवडा"</string>
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"संकुचित करा"</string>
<string name="menu_extract" msgid="8171946945982532262">"मध्ये काढा..."</string>
<string name="menu_rename" msgid="1883113442688817554">"पुनर्नामित करा"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"गुणधर्म"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"माहिती मिळवा"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> मध्ये पहा"</string>
<string name="menu_new_window" msgid="2947837751796109126">"नवीन विंडो"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"कट करा"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"हलवा"</string>
<string name="button_dismiss" msgid="7235249361023803349">"डिसमिस करा"</string>
<string name="button_retry" msgid="4011461781916631389">"पुन्हा प्रयत्न करा"</string>
+ <string name="button_clear" msgid="5412304437764369441">"साफ करा"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"पुरवठादारामध्ये दाखवा"</string>
<string name="not_sorted" msgid="7813496644889115530">"क्रमवारी लावलेली नाही"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"नाव"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"सारांश"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"प्रकार"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"आकार"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"सुधारित"</string>
- <string name="directory_children" msgid="8115290268549503262">"मुलांची संख्या"</string>
+ <string name="directory_items" msgid="6645621978998614003">"आयटमची संख्या"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"चढत्या क्रमाने"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"उतरत्या क्रमाने"</string>
<string name="drawer_open" msgid="8071673398187261741">"रूट दर्शवा"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"फाईल उघडू शकत नाही"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"संग्रहणांमध्ये फायली उघडू शकत नाही"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"काही दस्तऐवज हटविण्यात अक्षम"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"गुणधर्म लोड करू शकत नाही"</string>
<string name="share_via" msgid="8725082736005677161">"द्वारे सामायिक करा"</string>
<string name="copy_notification_title" msgid="52256435625098456">"फायली कॉपी करणे"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"फायली संकुचित करत आहे"</string>
@@ -111,11 +112,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> आयटम हटवत आहे.</item>
</plurals>
<string name="undo" msgid="2902438994196400565">"पूर्ववत करा"</string>
- <string name="copy_preparing" msgid="5326063807006898223">"कॉपी करण्यासाठी तयार करीत आहे…"</string>
+ <string name="copy_preparing" msgid="5326063807006898223">"कॉपी करण्यासाठी तयार करत आहे…"</string>
<string name="compress_preparing" msgid="6650018601382062672">"संकुचित करण्यासाठी तयार होत आहे…"</string>
<string name="extract_preparing" msgid="58266275455027829">"काढण्यासाठी तयार करत आहे..."</string>
<string name="move_preparing" msgid="8742573245485449429">"हलविण्यास तयार होत आहे…"</string>
- <string name="delete_preparing" msgid="6513863752916028147">"हटविण्यासाठी तयार करीत आहे..."</string>
+ <string name="delete_preparing" msgid="6513863752916028147">"हटविण्यासाठी तयार करत आहे..."</string>
<string name="delete_progress" msgid="2627631054702306423">"<xliff:g id="COUNT_0">%1$d</xliff:g> / <xliff:g id="TOTALCOUNT">%2$d</xliff:g>"</string>
<plurals name="copy_error_notification_title" formatted="false" msgid="3188432450429390963">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> आयटम कॉपी करु शकलो नाही</item>
@@ -196,10 +197,10 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> आयटम हटवायचा?</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> आयटम हटवायचे?</item>
</plurals>
- <string name="images_shortcut_label" msgid="2545168016070493574">"प्रतिमा"</string>
+ <string name="images_shortcut_label" msgid="2545168016070493574">"इमेज"</string>
<string name="archive_loading_failed" msgid="7243436722828766996">"ब्राउझिंगसाठी संग्रहण उघडण्यात अक्षम. फाइल एकतर दूषित झाली आहे किंवा असमर्थित स्वरूपात आहे."</string>
<string name="name_conflict" msgid="28407269328862986">"या नावाची फाइल आधीपासून अस्तित्वात आहे."</string>
- <string name="authentication_required" msgid="8030880723643436099">"निर्देशिका पाहण्यासाठी <xliff:g id="NAME">%1$s</xliff:g> मध्ये साइन इन करा"</string>
+ <string name="authentication_required" msgid="8030880723643436099">"डिरेक्टरी पाहण्यासाठी <xliff:g id="NAME">%1$s</xliff:g> मध्ये साइन इन करा"</string>
<string name="cant_display_content" msgid="8633226333229417237">"सामग्री प्रदर्शित करू शकत नाही"</string>
<string name="sign_in" msgid="6253762676723505592">"साइन इन करा"</string>
<string name="new_archive_file_name" msgid="1604650338077249838">"संग्रहण<xliff:g id="EXTENSION">%s</xliff:g>"</string>
diff --git a/res/values-ms/inspector_strings.xml b/res/values-ms/inspector_strings.xml
new file mode 100644
index 0000000..c6f214b
--- /dev/null
+++ b/res/values-ms/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Maklumat"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Maklumat fail tidak dapat dimuatkan"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Maklumat nyahpepijat (pembangun sahaja)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadata mentah: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Butiran media"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Jenis fail ini dibuka menggunakan"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Fail ini dibekalkan oleh"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Tidak dipilih"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Tidak diketahui"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensi"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinat"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitud"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Bukaan"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Kelajuan pengatup"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Tempoh"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Diambil pada"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Jarak fokus"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Setara ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artis"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Komposer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokasi"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Jenis strim"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Saiz mentah (bait)"</string>
+</resources>
diff --git a/res/values-ms/mimes.xml b/res/values-ms/mimes.xml
new file mode 100644
index 0000000..14a56d8
--- /dev/null
+++ b/res/values-ms/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Fail <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fail"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imej"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imej <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arkib <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplikasi Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Teks biasa"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Dokumen HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Dokumen PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Dokumen Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Pembentangan PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Hamparan Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Dokumen Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Hamparan Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Pembentangan Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Lukisan Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Jadual Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Borang Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Peta Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Tapak Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 35adcad..d156645 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Mampatkan"</string>
<string name="menu_extract" msgid="8171946945982532262">"Ekstrak ke…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Namakan semula"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Sifat"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Dapatkan maklumat"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Lihat dalam <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Tetingkap baharu"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Potong"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Alih"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ketepikan"</string>
<string name="button_retry" msgid="4011461781916631389">"Cuba Lagi"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Kosongkan"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Tunjukkan dalam pembekal"</string>
<string name="not_sorted" msgid="7813496644889115530">"Tidak diisih"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nama"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Ringkasan"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Jenis"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Saiz"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Diubah suai"</string>
- <string name="directory_children" msgid="8115290268549503262">"Bilangan Anak"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Bilangan item"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Menaik"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Menurun"</string>
<string name="drawer_open" msgid="8071673398187261741">"Tunjukkan akar"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Tidak dapat membuka fail"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Tidak dapat membuka fail dalam arkib"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Tidak dapat memadamkan sesetengah dokumen"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Sifat tidak dapat dimuatkan"</string>
<string name="share_via" msgid="8725082736005677161">"Kongsi melalui"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Menyalin fail"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Memampatkan fail"</string>
diff --git a/res/values-my/inspector_strings.xml b/res/values-my/inspector_strings.xml
new file mode 100644
index 0000000..af368f3
--- /dev/null
+++ b/res/values-my/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"အချက်အလက်"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ဖိုင်အချက်အလက်များကို ဖွင့်၍မရပါ"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"အမှားရှာပြင်ရန် အချက်အလက် (ဆော့ဖ်ဝဲအင်ဂျင်နီယာသာ)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"အကြမ်းထည် မက်တာဒေတာ− <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"မီဒီယာ အသေးစိတ်များ"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"၎င်းဖိုင်အမျိုးအစားကို ဖွင့်နိုင်သည့်အက်ပ်−"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ဤဖိုင်အား ဝန်ဆောင်ပေးသူ−"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"ရွေးမထားပါ"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"အမျိုးအမည်မသိ"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"အတိုင်းအတာများ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> − <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"ကိုဩဒိနိတ်များ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>၊ <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"အမြင့်"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"ကင်မရာ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"အလင်းဝင်ပေါက်"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ရှပ်တာအမြန်နှုန်း"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"ကြာချိန်"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ရိုက်ထားသည့်အချိန်−"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ဆုံတာ"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO နှုန်း"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"အနုပညာရှင်"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"ရေးစပ်သူ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"အယ်လ်ဘမ်"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"တည်နေရာ"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ထုတ်လွှင့်မှုအမျိုးအစားများ"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"အကြမ်းထည် အရွယ်အစား (ဘိုက်)"</string>
+</resources>
diff --git a/res/values-my/mimes.xml b/res/values-my/mimes.xml
new file mode 100644
index 0000000..23e75cb
--- /dev/null
+++ b/res/values-my/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ဖိုင်"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ဖိုင်"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"ပုံ"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> ပုံ"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"အသံ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> အသံ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ဗီဒီယို"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> ဗီဒီယို"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> မှတ်တမ်းဟောင်း"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android အပလီကေးရှင်း"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"ရိုးရိုးစာသား"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML နှင့်ရေးသည့်ဖိုင်"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ဖိုင်"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ဖိုင်"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint တင်ပြမှု"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel ဇယားကွက်"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google စာရွက်စာတမ်း"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google ဇယားကွက်"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google တင်ပြမှု"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ပုံ"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google ဇယား"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ဖောင်"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google မြေပုံ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google ဝဘ်ဆိုက်"</string>
+ <string name="directory_type" msgid="2702987727566226354">"အကန့်"</string>
+</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index f0ec986..b0d66e9 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"ချုံ့ရန်"</string>
<string name="menu_extract" msgid="8171946945982532262">"ရွှေးချယ်ထည့်သွင်းရန်…"</string>
<string name="menu_rename" msgid="1883113442688817554">"အမည်ပြောင်းပါ"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"သတ်မှတ်ချက်များ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"အချက်အလက် ရယူရန်"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> တွင် ကြည့်ရန်"</string>
<string name="menu_new_window" msgid="2947837751796109126">"ဝင်းဒိုးသစ်"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"ဖြတ်ယူပါ"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ရွှေ့ရန်"</string>
<string name="button_dismiss" msgid="7235249361023803349">"ပယ်ရန်"</string>
<string name="button_retry" msgid="4011461781916631389">"ပြန်စမ်းကြည့်ပါ"</string>
+ <string name="button_clear" msgid="5412304437764369441">"ရှင်းထုတ်ရန်"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"ပံ့ပိုးပေးသူတွင် ပြရန်"</string>
<string name="not_sorted" msgid="7813496644889115530">"စီမထားပါ"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"အမည်"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"အနှစ်ချုပ်"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"အမျိုးအစား"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"အရွယ်အစား"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"မွမ်းမံပြီး"</string>
- <string name="directory_children" msgid="8115290268549503262">"ကလေးအရေအတွက်"</string>
+ <string name="directory_items" msgid="6645621978998614003">"ပစ္စည်းအရေအတွက်"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ငယ်စဉ်ကြီးလိုက်"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"ကြီးစဉ်ငယ်လိုက်"</string>
<string name="drawer_open" msgid="8071673398187261741">"ပင်မဖိုင်တွဲများကို ပြပါ"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ဖိုင်ကို ဖွင့်၍မရပါ"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"မှတ်တမ်းဟောင်းထဲမှ ဖိုင်များကို ဖွင့်၍မရပါ"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"အချို့စာဖိုင်များကို ဖျက်၍မရပါ"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"သတ်မှတ်ချက်များကို ဖွင့်၍မရပါ"</string>
<string name="share_via" msgid="8725082736005677161">"အောက်ပါနည်းလမ်းဖြင့် မျှဝေပါ"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ဖိုင်များကူးယူနေသည်"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ဖိုင်များကို ချုံ့နေသည်"</string>
diff --git a/res/values-nb/inspector_strings.xml b/res/values-nb/inspector_strings.xml
new file mode 100644
index 0000000..cd315e6
--- /dev/null
+++ b/res/values-nb/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informasjon"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Kunne ikke laste inn filinformasjonen"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Feilsøkingsinfo (bare for utviklere)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Råmetadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Mediadetaljer"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Denne filtypen åpnes med"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Denne filen leveres av"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Ikke valgt"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Ukjent"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensjoner"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinater"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Høyde over havet"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Blender"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Lukkerhastighet"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Varighet"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Tatt"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Brennvidde"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Tilsvarende ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Komponist"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Posisjon"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Strømtyper"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Råstørrelse (byte)"</string>
+</resources>
diff --git a/res/values-nb/mimes.xml b/res/values-nb/mimes.xml
new file mode 100644
index 0000000..eb89ea2
--- /dev/null
+++ b/res/values-nb/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-fil"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fil"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Bilde"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-bilde"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Lyd"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-lyd"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-arkiv"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-app"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Ren tekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-presentasjon"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-regneark"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-regneark"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-presentasjon"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-tegning"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-tabell"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-skjema"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-kart"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-nettsted"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mappe"</string>
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index df75079..106371b 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Komprimer"</string>
<string name="menu_extract" msgid="8171946945982532262">"Pakk ut til …"</string>
<string name="menu_rename" msgid="1883113442688817554">"Gi nytt navn"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Egenskaper"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Hent inn informasjon"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Se i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nytt vindu"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Klipp ut"</string>
@@ -55,15 +55,17 @@
<string name="button_compress" msgid="8951561310857223966">"Komprimer"</string>
<string name="button_extract" msgid="1038674453689912247">"Pakk ut"</string>
<string name="button_move" msgid="8596460499325291272">"Flytt"</string>
- <string name="button_dismiss" msgid="7235249361023803349">"Avvis"</string>
+ <string name="button_dismiss" msgid="7235249361023803349">"Lukk"</string>
<string name="button_retry" msgid="4011461781916631389">"Prøv på nytt"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Fjern"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Vis i leverandøren"</string>
<string name="not_sorted" msgid="7813496644889115530">"Ikke sortert"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Navn"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Sammendrag"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Størrelse"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Endret"</string>
- <string name="directory_children" msgid="8115290268549503262">"Antall barn"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Antall elementer"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Stigende"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Synkende"</string>
<string name="drawer_open" msgid="8071673398187261741">"Vis røtter"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Kan ikke åpne filen"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Kan ikke åpne filer i arkiver"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Kunne ikke slette enkelte dokumenter"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Kunne ikke laste inn egenskapene"</string>
<string name="share_via" msgid="8725082736005677161">"Del via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopierer filer"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Komprimerer filer"</string>
diff --git a/res/values-ne/inspector_strings.xml b/res/values-ne/inspector_strings.xml
new file mode 100644
index 0000000..41102e4
--- /dev/null
+++ b/res/values-ne/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"जानकारी"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"फाइलसम्बन्धी जानकारी लोड गर्न सकिएन"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"डिबगसम्बन्धी जानकारी (विकासकर्ताका लागि मात्र)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"अप्रशोधित मेटाडेटा: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"मिडियासम्बन्धी विवरणहरू"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"यस प्रकारको फाइल निम्न अनुप्रयोगमार्फत खुल्छ"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"यो फाइलको प्रदायक"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"चयन गरिएको छैन"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"अज्ञात"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"उचाइ तथा चौडाइ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> एम. पि."</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"तस्बिर खिचेको स्थानका भौगोलिक स्थितिहरू"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"उचाइ"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"क्यामेरा"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"अपार्चर"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"सटरको गति"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"अवधि"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"तस्बिर खिचेको समय"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"फोकल लम्बाइ"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> मि. मि."</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO बराबर"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"कलाकार"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"रचनाकार"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"एल्बम"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"स्थान"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"स्ट्रिमका प्रकारहरू"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"अप्रशोधित आकार (बाइट)"</string>
+</resources>
diff --git a/res/values-ne/mimes.xml b/res/values-ne/mimes.xml
new file mode 100644
index 0000000..efbb6f4
--- /dev/null
+++ b/res/values-ne/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> फाइल"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"फाइल"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"छवि"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> छवि"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"अडियो"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> अडियो"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"भिडियो"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> भिडियो"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> अभिलेख"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android अनुप्रयोग"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"सामान्य पाठ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML कागजात"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF कागजात"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word कागजात"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint प्रस्तुतीकरण"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel स्प्रेडसिट"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google कागजात"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google स्प्रिेडसिट"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google प्रस्तुतीकरण"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google रेखाचित्र"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google तालिका"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google फारम"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google नक्सा"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google साइट"</string>
+ <string name="directory_type" msgid="2702987727566226354">"फोल्डर"</string>
+</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 1903f51..cada88e 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"कम्प्रेस गर्नुहोस्"</string>
<string name="menu_extract" msgid="8171946945982532262">"यसमा एकस्ट्र्याक्ट गर्नुहोस्…"</string>
<string name="menu_rename" msgid="1883113442688817554">"पुनःनामाकरण गर्नुहोस्"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"विशेषताहरू"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"जानकारी प्राप्त गर्नुहोस्"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> मा हेर्नुहोस्"</string>
<string name="menu_new_window" msgid="2947837751796109126">"नयाँ विन्डो"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"काट्नुहोस्"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"सार्नुहोस्"</string>
<string name="button_dismiss" msgid="7235249361023803349">"खारेज गर्नुहोस्"</string>
<string name="button_retry" msgid="4011461781916631389">"फेरि प्रयास गर्नुहोस्"</string>
+ <string name="button_clear" msgid="5412304437764369441">"खाली गर्नुहोस्"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"प्रदायकको सेवामा देखाउनुहोस्"</string>
<string name="not_sorted" msgid="7813496644889115530">"क्रमबद्ध गरिएको छैन"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"नाम"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"सारांश"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"प्रकार"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"आकार"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"परिमार्जित"</string>
- <string name="directory_children" msgid="8115290268549503262">"बालबालिकाहरूको सङ्ख्या"</string>
+ <string name="directory_items" msgid="6645621978998614003">"वस्तुहरूको संख्या"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"बढ्दो क्रम"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"घट्दो क्रम"</string>
<string name="drawer_open" msgid="8071673398187261741">"मूल ठाउँहरू देखाउनुहोस्"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"फाइल खोल्न सकिँदैन"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"अभिलेखहरूमा भएका फाइलहरू खोल्न सकिँदैन"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"केही कागजातहरूलाई मेट्न सकिएन"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"विशेषताहरू लोड गर्न सकिएन"</string>
<string name="share_via" msgid="8725082736005677161">"निम्न मार्फत साझेदारी गर्नुहोस्"</string>
<string name="copy_notification_title" msgid="52256435625098456">"फाइलहरूका प्रतिलिपि बनाउँदै"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"फाइलहरू कम्प्रेस गर्दै"</string>
diff --git a/res/values-nl/inspector_strings.xml b/res/values-nl/inspector_strings.xml
new file mode 100644
index 0000000..51e438e
--- /dev/null
+++ b/res/values-nl/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informatie"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Bestandsgegevens kunnen niet worden geladen"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Foutopsporingsinfo (alleen ontwikkelaars)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Onbewerkte metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Mediagegevens"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Dit type bestand wordt geopend met"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Dit bestand wordt geleverd door"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Niet geselecteerd"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Onbekend"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Afmetingen"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coördinaten"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Hoogte"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Diafragma"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Sluitersnelheid"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duur"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Gemaakt op"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Focuslengte"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-equivalent"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artiest"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Componist"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Locatie"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Streamtypen"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Onbewerkte grootte (bytes)"</string>
+</resources>
diff --git a/res/values-nl/mimes.xml b/res/values-nl/mimes.xml
new file mode 100644
index 0000000..1f762be
--- /dev/null
+++ b/res/values-nl/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-bestand"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Bestand"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Afbeelding"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-afbeelding"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-archief"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-app"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Platte tekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-document"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Pdf-document"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-document"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-presentatie"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-spreadsheet"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-document"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-spreadsheet"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-presentatie"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-tekening"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-tabel"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-formulier"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-kaart"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Map"</string>
+</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 0124f8a..6b864f9 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimeren"</string>
<string name="menu_extract" msgid="8171946945982532262">"Uitpakken naar…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Naam wijzigen"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Eigenschappen"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Informatie bekijken"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Bekijken in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nieuw venster"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Knippen"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Verplaatsen"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Sluiten"</string>
<string name="button_retry" msgid="4011461781916631389">"Opnieuw proberen"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Wissen"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Weergeven in provider"</string>
<string name="not_sorted" msgid="7813496644889115530">"Niet gesorteerd"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Naam"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Overzicht"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Type"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Grootte"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Aangepast"</string>
- <string name="directory_children" msgid="8115290268549503262">"Aantal kinderen"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Aantal items"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Oplopend"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Aflopend"</string>
<string name="drawer_open" msgid="8071673398187261741">"Roots weergeven"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Kan bestand niet openen"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Kan bestanden in archieven niet openen"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Kan bepaalde documenten niet verwijderen"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Eigenschappen kunnen niet worden geladen"</string>
<string name="share_via" msgid="8725082736005677161">"Delen via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Bestanden kopiëren"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Bestanden comprimeren"</string>
diff --git a/res/values-pa/inspector_strings.xml b/res/values-pa/inspector_strings.xml
new file mode 100644
index 0000000..117a840
--- /dev/null
+++ b/res/values-pa/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"ਜਾਣਕਾਰੀ"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ਫ਼ਾਈਲ ਜਾਣਕਾਰੀ ਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ਡੀਬੱਗ ਜਾਣਕਾਰੀ (ਸਿਰਫ਼ ਵਿਕਾਸਕਾਰ)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"ਰਾਅ ਮੈਟਾਡਾਟਾ: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"ਮੀਡੀਆ ਦੇ ਵੇਰਵੇ"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ਇਸ ਕਿਸਮ ਦੀ ਫ਼ਾਈਲ ਇਸ ਨਾਲ ਖੁੱਲ੍ਹਦੀ ਹੈ:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ਇਹ ਫ਼ਾਈਲ ਇਹਨਾਂ ਵੱਲੋਂ ਦਿੱਤੀ ਗਈ ਹੈ:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"ਚੁਣੀ ਨਹੀਂ ਗਈ"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"ਅਗਿਆਤ"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ਮਾਪ"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> ਮੈਗਾ ਪਿਕਸਲ"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"ਲੰਬਕਾਰ ਅਤੇ ਵਿਥਕਾਰ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ਉਚਾਈ"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"ਕੈਮਰਾ"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"ਕੈਮਰੇ ਦੀ ਮੋਰੀ"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ਸ਼ਟਰ ਦੀ ਗਤੀ"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"ਮਿਆਦ"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ਇਸ ਮਿਤੀ ਨੂੰ ਖਿੱਚੀ ਗਈ:"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ਫੋਕਲ ਲੰਬਾਈ"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>ਮਿ.ਮੀ."</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ਦੇ ਬਰਾਬਰ"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"ਕਲਾਕਾਰ"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"ਗੀਤਕਾਰ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ਐਲਬਮ"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"ਟਿਕਾਣਾ"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ਸਟ੍ਰੀਮ ਦੀਆਂ ਕਿਸਮਾਂ"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw ਆਕਾਰ (ਬਾਈਟ)"</string>
+</resources>
diff --git a/res/values-pa/mimes.xml b/res/values-pa/mimes.xml
new file mode 100644
index 0000000..94969c5
--- /dev/null
+++ b/res/values-pa/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ਫ਼ਾਈਲ"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ਫ਼ਾਈਲ"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"ਚਿੱਤਰ"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> ਚਿੱਤਰ"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">" ਆਡੀਓ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ਆਡੀਓ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ਵੀਡੀਓ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> ਵੀਡੀਓ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> ਪੁਰਾਲੇਖ"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android ਐਪਲੀਕੇਸ਼ਨ"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"ਸਰਲ ਲਿਖਤ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML ਦਸਤਾਵੇਜ਼"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ਦਸਤਾਵੇਜ਼"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ਦਸਤਾਵੇਜ਼"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint ਪੇਸ਼ਕਾਰੀ"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel ਸਪਰੈੱਡਸ਼ੀਟ"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google ਦਸਤਾਵੇਜ਼"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google ਸਪਰੈੱਡਸ਼ੀਟ"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google ਪੇਸ਼ਕਾਰੀ"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ਚਿੱਤਰਕਾਰੀ"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google ਸਾਰਨੀ"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ਫ਼ਾਰਮ"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google ਨਕਸ਼ਾ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google ਸਾਈਟ"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ਫੋਲਡਰ"</string>
+</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index abe79b3..0a320ae 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -27,7 +27,7 @@
<string name="menu_create_dir" msgid="2413624798689091042">"ਨਵਾਂ ਫੋਲਡਰ"</string>
<string name="menu_grid" msgid="1453636521731880680">"ਗਰਿੱਡ ਦ੍ਰਿਸ਼"</string>
<string name="menu_list" msgid="6714267452146410402">"ਸੂਚੀ ਦ੍ਰਿਸ਼"</string>
- <string name="menu_search" msgid="1876699106790719849">"ਖੋਜ"</string>
+ <string name="menu_search" msgid="1876699106790719849">"ਖੋਜੋ"</string>
<string name="menu_settings" msgid="6520844520117939047">"ਸਟੋਰੇਜ ਸੈਟਿੰਗਾਂ"</string>
<string name="menu_open" msgid="9092138100049759315">"ਖੋਲ੍ਹੋ"</string>
<string name="menu_open_with" msgid="5507647065467520229">"ਇਸ ਨਾਲ ਖੋਲ੍ਹੋ"</string>
@@ -41,14 +41,14 @@
<string name="menu_compress" msgid="37539111904724188">"ਆਕਾਰ ਛੋਟਾ ਕਰੋ"</string>
<string name="menu_extract" msgid="8171946945982532262">"ਇਸ ਵਿੱਚ ਐਕਸਟ੍ਰੈਕਟ ਕਰੋ…"</string>
<string name="menu_rename" msgid="1883113442688817554">"ਮੁੜ-ਨਾਮਕਰਨ ਕਰੋ"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ"</string>
- <string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> ਵਿੱਚ ਵੇਖੋ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+ <string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> ਵਿੱਚ ਦੇਖੋ"</string>
<string name="menu_new_window" msgid="2947837751796109126">"ਨਵੀਂ ਵਿੰਡੋ"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"ਕੱਟੋ"</string>
<string name="menu_copy_to_clipboard" msgid="5064081159073330776">"ਕਾਪੀ ਕਰੋ"</string>
<string name="menu_paste_from_clipboard" msgid="360947260414135827">"ਪੇਸਟ ਕਰੋ"</string>
<string name="menu_paste_into_folder" msgid="8000644546983240101">"ਫੋਲਡਰ ਵਿੱਚ ਪੇਸਟ ਕਰੋ"</string>
- <string name="menu_advanced_show" msgid="7558626506462906726">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ ਵਿਖਾਓ"</string>
+ <string name="menu_advanced_show" msgid="7558626506462906726">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ ਦਿਖਾਓ"</string>
<string name="menu_advanced_hide" msgid="6488381508009246334">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ ਲੁਕਾਓ"</string>
<string name="button_select" msgid="240863497069321364">"ਚੁਣੋ"</string>
<string name="button_copy" msgid="8219059853840996027">"ਕਾਪੀ ਕਰੋ"</string>
@@ -57,16 +57,18 @@
<string name="button_move" msgid="8596460499325291272">"ਤਬਦੀਲ ਕਰੋ"</string>
<string name="button_dismiss" msgid="7235249361023803349">"ਖਾਰਜ ਕਰੋ"</string>
<string name="button_retry" msgid="4011461781916631389">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+ <string name="button_clear" msgid="5412304437764369441">"ਕਲੀਅਰ ਕਰੋ"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"ਪ੍ਰਦਾਨਕ ਸੇਵਾ ਵਿੱਚ ਦਿਖਾਓ"</string>
<string name="not_sorted" msgid="7813496644889115530">"ਛਾਂਟੀ ਨਹੀਂ ਕੀਤੀ ਗਈ"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"ਨਾਮ"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"ਸਾਰਾਂਸ਼"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ਕਿਸਮ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"ਆਕਾਰ"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"ਸੋਧਣ ਦਾ ਸਮਾਂ"</string>
- <string name="directory_children" msgid="8115290268549503262">"ਬੱਚਿਆਂ ਦੀ ਗਿਣਤੀ"</string>
+ <string name="directory_items" msgid="6645621978998614003">"ਆਈਟਮਾਂ ਦੀ ਗਿਣਤੀ"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ਵਧਦਾ ਕ੍ਰਮ"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"ਘਟਦਾ ਕ੍ਰਮ"</string>
- <string name="drawer_open" msgid="8071673398187261741">"ਰੂਟਾਂ ਨੂੰ ਵਿਖਾਓ"</string>
+ <string name="drawer_open" msgid="8071673398187261741">"ਰੂਟਾਂ ਨੂੰ ਦਿਖਾਓ"</string>
<string name="drawer_close" msgid="4263880768630848848">"ਰੂਟਾਂ ਨੂੰ ਲੁਕਾਓ"</string>
<string name="save_error" msgid="8631128801982095782">"ਦਸਾਤਵੇਜ਼ ਰੱਖਿਅਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
<string name="create_error" msgid="3092144450044861994">"ਫੋਲਡਰ ਬਣਾਉਣਾ ਅਸਫਲ ਰਿਹਾ"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ਫ਼ਾਈਲ ਨੂੰ ਖੋਲ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"ਪੁਰਾਲੇਖਾਂ ਵਿੱਚ ਫ਼ਾਈਲਾਂ ਨੂੰ ਖੋਲ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"ਕੁਝ ਦਸਤਾਵੇਜ਼ਾਂ ਨੂੰ ਮਿਟਾਉਣ ਦੇ ਅਯੋਗ"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
<string name="share_via" msgid="8725082736005677161">"ਇਸ ਰਾਹੀਂ ਸਾਂਝਾ ਕਰੋ"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ਫ਼ਾਈਲਾਂ ਕਾਪੀ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ਆਕਾਰ ਛੋਟਾ ਕੀਤਾ ਜਾ ਰਿਹਾ"</string>
@@ -115,7 +116,7 @@
<string name="compress_preparing" msgid="6650018601382062672">"ਆਕਾਰ ਛੋਟਾ ਕਰਨ ਦੀ ਤਿਆਰੀ ਅਧੀਨ…"</string>
<string name="extract_preparing" msgid="58266275455027829">"ਐਕਸਟ੍ਰੈਕਟ ਕਰਨ ਦੀ ਤਿਆਰੀ…"</string>
<string name="move_preparing" msgid="8742573245485449429">"ਤਬਦੀਲ ਕਰਨ ਦੀ ਤਿਆਰੀ ਹੋ ਰਹੀ ਹੈ…"</string>
- <string name="delete_preparing" msgid="6513863752916028147">"ਮਿਟਾਉਣ ਦੀ ਤਿਆਰੀ ਹੋ ਰਹੀ ਹੈ…"</string>
+ <string name="delete_preparing" msgid="6513863752916028147">"ਮਿਟਾਉਣ ਦੀ ਤਿਆਰੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
<string name="delete_progress" msgid="2627631054702306423">"<xliff:g id="COUNT_0">%1$d</xliff:g> / <xliff:g id="TOTALCOUNT">%2$d</xliff:g>"</string>
<plurals name="copy_error_notification_title" formatted="false" msgid="3188432450429390963">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ਆਈਟਮਾਂ ਨੂੰ ਕਾਪੀ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ</item>
@@ -133,7 +134,7 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ਆਈਟਮਾਂ ਨੂੰ ਮਿਟਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ਆਈਟਮਾਂ ਨੂੰ ਮਿਟਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ</item>
</plurals>
- <string name="notification_touch_for_details" msgid="2385563502445129570">"ਵੇਰਵਿਆਂ ਨੂੰ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="notification_touch_for_details" msgid="2385563502445129570">"ਵੇਰਵਿਆਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="close" msgid="905969391788869975">"ਬੰਦ ਕਰੋ"</string>
<plurals name="copy_failure_alert_content" formatted="false" msgid="5570549471912990536">
<item quantity="one">ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਕਾਪੀ ਨਹੀਂ ਕੀਤਾ ਗਿਆ: <xliff:g id="LIST_1">%1$s</xliff:g></item>
@@ -156,8 +157,8 @@
<item quantity="other">ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਨਹੀਂ ਮਿਟਾਇਆ ਗਿਆ: <xliff:g id="LIST_1">%1$s</xliff:g></item>
</plurals>
<plurals name="copy_converted_warning_content" formatted="false" msgid="7433742181712126588">
- <item quantity="one">ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਕਿਸੇ ਹੋਰ ਵੰਨਗੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ: <xliff:g id="LIST_1">%1$s</xliff:g></item>
- <item quantity="other">ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਕਿਸੇ ਹੋਰ ਵੰਨਗੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਕਿਸੇ ਹੋਰ ਫਾਰਮੈਟ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="other">ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਕਿਸੇ ਹੋਰ ਫਾਰਮੈਟ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ: <xliff:g id="LIST_1">%1$s</xliff:g></item>
</plurals>
<plurals name="clipboard_files_clipped" formatted="false" msgid="4847061634862926902">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ਆਈਟਮਾਂ ਨੂੰ ਕਲਿੱਪਬੋਰਡ \'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ।</item>
@@ -170,7 +171,7 @@
<string name="notification_copy_files_converted_title" msgid="6916768494891833365">"ਕੁਝ ਫ਼ਾਈਲਾਂ ਦਾ ਰੂਪਾਂਤਰਨ ਕੀਤਾ ਗਿਆ ਸੀ"</string>
<string name="open_external_dialog_request" msgid="8173558471322861268">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="STORAGE"><i>^3</i></xliff:g> \'ਤੇ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ਡਾਇਰੈਕਟਰੀ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
<string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ਡਾਇਰੈਕਟਰੀ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
- <string name="open_external_dialog_root_request" msgid="6776729293982633">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="STORAGE"><i>^2</i></xliff:g> ਉੱਪਰ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਸਮੇਤ ਤੁਹਾਡੇ ਡੈਟੇ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
+ <string name="open_external_dialog_root_request" msgid="6776729293982633">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="STORAGE"><i>^2</i></xliff:g> ਉੱਪਰ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਸਮੇਤ ਤੁਹਾਡੇ ਡਾਟਾ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
<string name="never_ask_again" msgid="525908236522201138">"ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
<string name="allow" msgid="1275746941353040309">"ਇਜਾਜ਼ਤ ਦਿਓ"</string>
<string name="deny" msgid="5127201668078153379">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
@@ -197,11 +198,11 @@
<item quantity="other">ਕੀ <xliff:g id="COUNT_1">%1$d</xliff:g> ਆਈਟਮਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?</item>
</plurals>
<string name="images_shortcut_label" msgid="2545168016070493574">"ਚਿੱਤਰ"</string>
- <string name="archive_loading_failed" msgid="7243436722828766996">"ਬ੍ਰਾਊਜ਼ਿੰਗ ਲਈ ਪੁਰਾਲੇਖ ਨੂੰ ਖੋਲ੍ਹਣ ਦੇ ਅਯੋਗ ਹੈ। ਫ਼ਾਈਲ ਜਾਂ ਤਾਂ ਖਰਾਬ ਹੈ, ਜਾਂ ਅਸਮਰਥਿਤ ਵੰਨਗੀ ਵਿੱਚ ਹੈ।"</string>
+ <string name="archive_loading_failed" msgid="7243436722828766996">"ਬ੍ਰਾਊਜ਼ਿੰਗ ਲਈ ਪੁਰਾਲੇਖ ਨੂੰ ਖੋਲ੍ਹਣ ਦੇ ਅਯੋਗ ਹੈ। ਫ਼ਾਈਲ ਜਾਂ ਤਾਂ ਖਰਾਬ ਹੈ, ਜਾਂ ਅਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਹੈ।"</string>
<string name="name_conflict" msgid="28407269328862986">"ਇਸ ਨਾਮ ਵਾਲੀ ਫ਼ਾਈਲ ਪਹਿਲਾਂ ਤੋਂ ਮੌਜੂਦ ਹੈ।"</string>
- <string name="authentication_required" msgid="8030880723643436099">"ਇਸ ਡਾਇਰੈਕਟਰੀ ਨੂੰ ਦੇਖਣ ਲਈ, <xliff:g id="NAME">%1$s</xliff:g> \'ਤੇ ਸਾਈਨ ਇਨ ਕਰੋ"</string>
- <string name="cant_display_content" msgid="8633226333229417237">"ਸਮੱਗਰੀਆਂ ਦਿਖਾਈਆਂ ਨਹੀਂ ਜਾ ਸਕਦੀਆਂ"</string>
- <string name="sign_in" msgid="6253762676723505592">"ਸਾਈਨ ਇਨ ਕਰੋ"</string>
+ <string name="authentication_required" msgid="8030880723643436099">"ਇਸ ਡਾਇਰੈਕਟਰੀ ਨੂੰ ਦੇਖਣ ਲਈ, <xliff:g id="NAME">%1$s</xliff:g> \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
+ <string name="cant_display_content" msgid="8633226333229417237">"ਸਮੱਗਰੀਆਂ ਪ੍ਰਦਰਸ਼ਿਤ ਨਹੀਂ ਕੀਤੀਆਂ ਜਾ ਸਕਦੀਆਂ"</string>
+ <string name="sign_in" msgid="6253762676723505592">"ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
<string name="new_archive_file_name" msgid="1604650338077249838">"ਪੁਰਾਲੇਖ<xliff:g id="EXTENSION">%s</xliff:g>"</string>
<string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"<xliff:g id="NAME">%1$s</xliff:g> ਉੱਤੇ ਲਿਖੀਏ?"</string>
<string name="continue_in_background" msgid="1974214559047793331">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਜਾਰੀ ਰੱਖੋ"</string>
diff --git a/res/values-pl/inspector_strings.xml b/res/values-pl/inspector_strings.xml
new file mode 100644
index 0000000..e17ccd9
--- /dev/null
+++ b/res/values-pl/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informacje"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Nie udało się załadować informacji o pliku"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informacje o debugowaniu (tylko programiści)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadane pliku RAW: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Informacje o pliku multimedialnym"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ten rodzaj pliku możesz otworzyć w:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Dostawca pliku:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nie wybrano"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Nieznana"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Wymiary"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Współrzędne"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Wysokość"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Aparat"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Przysłona"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Szybkość migawki"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Czas"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Data wykonania"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Ogniskowa"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Równoważnik ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Wykonawca"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Kompozytor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokalizacja"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Typy strumienia"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Rzeczywisty rozmiar pliku (bajty)"</string>
+</resources>
diff --git a/res/values-pl/mimes.xml b/res/values-pl/mimes.xml
new file mode 100644
index 0000000..6e96f69
--- /dev/null
+++ b/res/values-pl/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Plik <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Plik"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Zdjęcie"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Obraz <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Plik audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Plik audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Plik wideo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Plik wideo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archiwum <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplikacja na Androida"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Zwykły tekst"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Dokument HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Dokument PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Dokument Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Prezentacja PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Arkusz kalkulacyjny Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Dokument Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Arkusz kalkulacyjny Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Prezentacja Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Rysunek Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabela Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formularz Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Witryna Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 4949a69..13c3264 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Skompresuj"</string>
<string name="menu_extract" msgid="8171946945982532262">"Rozpakuj do…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Zmień nazwę"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Właściwości"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Zobacz informacje"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Zobacz w: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nowe okno"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Wytnij"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Przenieś"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Odrzuć"</string>
<string name="button_retry" msgid="4011461781916631389">"Spróbuj jeszcze raz"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Zrezygnuj"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Pokaż w usłudze"</string>
<string name="not_sorted" msgid="7813496644889115530">"Brak sortowania"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nazwa"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Podsumowanie"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Typ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Rozmiar"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Zmieniono"</string>
- <string name="directory_children" msgid="8115290268549503262">"Liczba dzieci"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Liczba elementów"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Rosnąco"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Malejąco"</string>
<string name="drawer_open" msgid="8071673398187261741">"Pokaż elementy główne"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Nie można otworzyć pliku"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Nie można otworzyć plików w archiwum"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nie można usunąć niektórych dokumentów"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Nie udało się załadować właściwości"</string>
<string name="share_via" msgid="8725082736005677161">"Udostępnij przez"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopiowanie plików"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Kompresuję pliki"</string>
diff --git a/res/values-pt-rBR/inspector_strings.xml b/res/values-pt-rBR/inspector_strings.xml
new file mode 100644
index 0000000..03d2545
--- /dev/null
+++ b/res/values-pt-rBR/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informações"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Não foi possível carregar as informações do arquivo"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Info de depuração (apenas desenvolvimento)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadados brutos: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalhes de mídia"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Este tipo de arquivo é aberto no app"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Este arquivo é fornecido por"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Não selecionado"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Desconhecido"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensões"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordenadas"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Câmera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Abertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocidade do obturador"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duração"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Tirada em"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Distância focal:"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Equivalente de ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Álbum"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Localização"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipos de stream"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Tamanho bruto (bytes)"</string>
+</resources>
diff --git a/res/values-pt-rBR/mimes.xml b/res/values-pt-rBR/mimes.xml
new file mode 100644
index 0000000..07dd5e2
--- /dev/null
+++ b/res/values-pt-rBR/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Arquivo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Arquivo"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imagem"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imagem <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Áudio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Áudio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vídeo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vídeo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arquivo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicativo Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texto simples"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Documento HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Documento PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Documento do Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Apresentação PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Planilha do Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Documento do Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Planilha do Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Apresentação do Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Desenho do Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabela do Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulário do Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa do Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Site do Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Pasta"</string>
+</resources>
diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml
index 3ee2c03..af691a1 100644
--- a/res/values-pt-rBR/strings.xml
+++ b/res/values-pt-rBR/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Compactar"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extrair para…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Renomear"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propriedades"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Ver informações"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Ver em <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nova janela"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Recortar"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mover"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Dispensar"</string>
<string name="button_retry" msgid="4011461781916631389">"Tentar novamente"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Limpar"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostrar no provedor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sem classificação"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nome"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Resumo"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Tamanho"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modificação"</string>
- <string name="directory_children" msgid="8115290268549503262">"Número de filhos"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Número de itens"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Crescente"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Decrescente"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostrar raízes"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Não é possível abrir o arquivo"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Não é possível abrir itens arquivados"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Não foi possível excluir alguns documentos"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Não foi possível carregar as propriedades"</string>
<string name="share_via" msgid="8725082736005677161">"Compartilhar via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copiando arquivos"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compactando arquivos"</string>
diff --git a/res/values-pt-rPT/inspector_strings.xml b/res/values-pt-rPT/inspector_strings.xml
new file mode 100644
index 0000000..2b63c49
--- /dev/null
+++ b/res/values-pt-rPT/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informações"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Não foi possível carregar as informações do ficheiro"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informação de depuração (apenas programadores)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadados não processados: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalhes de multimédia"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Este tipo de ficheiro abre com a aplicação"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Este ficheiro é fornecido por"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Não selecionada"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Desconhecida"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensões"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordenadas"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Câmara"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Abertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocidade do obturador"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duração"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Tirada em"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Distância focal"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Equivalente de ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Álbum"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Localização"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipos de transmissão"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Tamanho não processado (bytes)"</string>
+</resources>
diff --git a/res/values-pt-rPT/mimes.xml b/res/values-pt-rPT/mimes.xml
new file mode 100644
index 0000000..ec8d2fd
--- /dev/null
+++ b/res/values-pt-rPT/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Ficheiro <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Ficheiro"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imagem"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imagem <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Áudio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Áudio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vídeo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vídeo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arquivo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicação Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texto simples"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Documento HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Documento PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Documento do Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Apresentação PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Folha de cálculo Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Documento do Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Folha de cálculo do Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Apresentação do Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Desenho do Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabela do Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulário do Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa do Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Site do Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Pasta"</string>
+</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 4a24854..9a71ed4 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimir"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extrair para…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Mudar o nome"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propriedades"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Obter informações"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Ver no <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nova janela"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cortar"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mover"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ignorar"</string>
<string name="button_retry" msgid="4011461781916631389">"Tentar novamente"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Limpar"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostrar no fornecedor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Não ordenados"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nome"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Resumo"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Tamanho"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modificado"</string>
- <string name="directory_children" msgid="8115290268549503262">"Número de crianças"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Número de itens"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Ascendente"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Descendente"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostrar raízes"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Não é possível abrir o ficheiro"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Não é possível abrir ficheiros nos arquivos"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Não é possível eliminar alguns documentos"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Não foi possível carregar as propriedades"</string>
<string name="share_via" msgid="8725082736005677161">"Partilhar através de"</string>
<string name="copy_notification_title" msgid="52256435625098456">"A copiar ficheiros"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"A comprimir ficheiros…"</string>
@@ -91,24 +92,24 @@
<string name="delete_notification_title" msgid="2512757431856830792">"A eliminar ficheiros"</string>
<string name="copy_remaining" msgid="5390517377265177727">"Faltam <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="151184708996738192">
- <item quantity="one">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
- <item quantity="other">A copiar <xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="other">A copiar <xliff:g id="COUNT_1">%1$d</xliff:g> itens…</item>
+ <item quantity="one">A copiar <xliff:g id="COUNT_0">%1$d</xliff:g> item…</item>
</plurals>
<plurals name="compress_begin" formatted="false" msgid="3534158317098678895">
- <item quantity="one">Compressing <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
<item quantity="other">A comprimir <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros…</item>
+ <item quantity="one">A comprimir <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro…</item>
</plurals>
<plurals name="extract_begin" formatted="false" msgid="1006380679562903749">
- <item quantity="one">Extracting <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
<item quantity="other">A extrair <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros…</item>
+ <item quantity="one">A extrair <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro…</item>
</plurals>
<plurals name="move_begin" formatted="false" msgid="1464229874265756956">
- <item quantity="one">Moving <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
- <item quantity="other">A mover <xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="other">A mover <xliff:g id="COUNT_1">%1$d</xliff:g> itens…</item>
+ <item quantity="one">A mover <xliff:g id="COUNT_0">%1$d</xliff:g> item…</item>
</plurals>
<plurals name="deleting" formatted="false" msgid="1729138001178158901">
- <item quantity="one">Deleting <xliff:g id="COUNT_1">%1$d</xliff:g> items.</item>
- <item quantity="other">A eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="other">A eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> itens…</item>
+ <item quantity="one">A eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> item…</item>
</plurals>
<string name="undo" msgid="2902438994196400565">"Anular"</string>
<string name="copy_preparing" msgid="5326063807006898223">"A preparar para copiar…"</string>
@@ -118,50 +119,50 @@
<string name="delete_preparing" msgid="6513863752916028147">"A preparar para eliminar…"</string>
<string name="delete_progress" msgid="2627631054702306423">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="TOTALCOUNT">%2$d</xliff:g>"</string>
<plurals name="copy_error_notification_title" formatted="false" msgid="3188432450429390963">
- <item quantity="one">Couldn’t copy <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
<item quantity="other">Não foi possível copiar <xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="one">Não foi possível copiar <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
</plurals>
<plurals name="compress_error_notification_title" formatted="false" msgid="3043630066678213644">
- <item quantity="one">Couldn’t compress <xliff:g id="COUNT_1">%1$d</xliff:g> files</item>
<item quantity="other">Não foi possível comprimir <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros</item>
+ <item quantity="one">Não foi possível comprimir <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro</item>
</plurals>
<plurals name="move_error_notification_title" formatted="false" msgid="2185736082411854754">
- <item quantity="one">Couldn’t move <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
<item quantity="other">Não foi possível mover <xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="one">Não foi possível mover <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
</plurals>
<plurals name="delete_error_notification_title" formatted="false" msgid="7568122018481625267">
- <item quantity="one">Couldn’t delete <xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
<item quantity="other">Não foi possível eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="one">Não foi possível eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
</plurals>
<string name="notification_touch_for_details" msgid="2385563502445129570">"Tocar para ver detalhes"</string>
<string name="close" msgid="905969391788869975">"Fechar"</string>
<plurals name="copy_failure_alert_content" formatted="false" msgid="5570549471912990536">
- <item quantity="one">These files weren’t copied: <xliff:g id="LIST_1">%1$s</xliff:g></item>
<item quantity="other">Estes ficheiros não foram copiados: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">Este ficheiro não foi copiado: <xliff:g id="LIST_0">%1$s</xliff:g></item>
</plurals>
<plurals name="compress_failure_alert_content" formatted="false" msgid="5760632881868842400">
- <item quantity="one">These files weren’t compressed: <xliff:g id="LIST_1">%1$s</xliff:g></item>
<item quantity="other">Estes ficheiros não foram comprimidos: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">Este ficheiro não foi comprimido: <xliff:g id="LIST_0">%1$s</xliff:g></item>
</plurals>
<plurals name="extract_failure_alert_content" formatted="false" msgid="7572748127571720803">
- <item quantity="one">These files weren’t extracted: <xliff:g id="LIST_1">%1$s</xliff:g></item>
<item quantity="other">Estes ficheiros não foram extraídos: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">Este ficheiro não foi extraído: <xliff:g id="LIST_0">%1$s</xliff:g></item>
</plurals>
<plurals name="move_failure_alert_content" formatted="false" msgid="2747390342670799196">
- <item quantity="one">These files weren’t moved: <xliff:g id="LIST_1">%1$s</xliff:g></item>
<item quantity="other">Estes ficheiros não foram movidos: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">Este ficheiro não foi movido: <xliff:g id="LIST_0">%1$s</xliff:g></item>
</plurals>
<plurals name="delete_failure_alert_content" formatted="false" msgid="6122372614839711711">
- <item quantity="one">These files weren’t deleted: <xliff:g id="LIST_1">%1$s</xliff:g></item>
<item quantity="other">Estes ficheiros não foram eliminados: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">Este ficheiro não foi eliminado: <xliff:g id="LIST_0">%1$s</xliff:g></item>
</plurals>
<plurals name="copy_converted_warning_content" formatted="false" msgid="7433742181712126588">
- <item quantity="one">These files were converted to another format: <xliff:g id="LIST_1">%1$s</xliff:g></item>
<item quantity="other">Estes ficheiros foram convertidos para outro formato: <xliff:g id="LIST_1">%1$s</xliff:g></item>
+ <item quantity="one">Este ficheiro foi convertido para outro formato: <xliff:g id="LIST_0">%1$s</xliff:g></item>
</plurals>
<plurals name="clipboard_files_clipped" formatted="false" msgid="4847061634862926902">
- <item quantity="one">Copied <xliff:g id="COUNT_1">%1$d</xliff:g> items to clipboard.</item>
- <item quantity="other">Foram copiados <xliff:g id="COUNT_1">%1$d</xliff:g> itens para a área de transferência</item>
+ <item quantity="other">Copiou <xliff:g id="COUNT_1">%1$d</xliff:g> itens para a área de transferência.</item>
+ <item quantity="one">Copiou <xliff:g id="COUNT_0">%1$d</xliff:g> item para a área de transferência.</item>
</plurals>
<string name="file_operation_rejected" msgid="4301554203329008794">"O ficheiro não permite a operação."</string>
<string name="file_operation_error" msgid="2234357335716533795">"Falha na operação do ficheiro."</string>
@@ -175,26 +176,26 @@
<string name="allow" msgid="1275746941353040309">"Permitir"</string>
<string name="deny" msgid="5127201668078153379">"Recusar"</string>
<plurals name="elements_selected" formatted="false" msgid="4448165978637163692">
- <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item>
</plurals>
<plurals name="elements_dragged" formatted="false" msgid="5932571296037626279">
- <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
</plurals>
<string name="delete_filename_confirmation_message" msgid="8338069763240613258">"Pretende eliminar \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="9084085260877704140">"Pretende eliminar a pasta \"<xliff:g id="NAME">%1$s</xliff:g>\" e os respetivos conteúdos?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="4866664063250034142">
- <item quantity="one">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
<item quantity="other">Pretende eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
+ <item quantity="one">Pretende eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
</plurals>
<plurals name="delete_folders_confirmation_message" formatted="false" msgid="1028946402799686388">
- <item quantity="one">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> folders and their contents?</item>
<item quantity="other">Pretende eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> pastas e os respetivos conteúdos?</item>
+ <item quantity="one">Pretende eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> pasta e os respetivos conteúdos?</item>
</plurals>
<plurals name="delete_items_confirmation_message" formatted="false" msgid="7285090426511028179">
- <item quantity="one">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> items?</item>
<item quantity="other">Pretende eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> itens?</item>
+ <item quantity="one">Pretende eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> item?</item>
</plurals>
<string name="images_shortcut_label" msgid="2545168016070493574">"Imagens"</string>
<string name="archive_loading_failed" msgid="7243436722828766996">"Não é possível abrir o arquivo para navegação. O ficheiro está danificado ou está num formato que não é suportado."</string>
diff --git a/res/values-pt/inspector_strings.xml b/res/values-pt/inspector_strings.xml
new file mode 100644
index 0000000..03d2545
--- /dev/null
+++ b/res/values-pt/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informações"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Não foi possível carregar as informações do arquivo"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Info de depuração (apenas desenvolvimento)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadados brutos: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalhes de mídia"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Este tipo de arquivo é aberto no app"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Este arquivo é fornecido por"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Não selecionado"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Desconhecido"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensões"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordenadas"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Câmera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Abertura"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocidade do obturador"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Duração"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Tirada em"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Distância focal:"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Equivalente de ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artista"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compositor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Álbum"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Localização"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipos de stream"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Tamanho bruto (bytes)"</string>
+</resources>
diff --git a/res/values-pt/mimes.xml b/res/values-pt/mimes.xml
new file mode 100644
index 0000000..07dd5e2
--- /dev/null
+++ b/res/values-pt/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Arquivo <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Arquivo"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imagem"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imagem <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Áudio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Áudio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Vídeo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Vídeo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arquivo <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicativo Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Texto simples"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Documento HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Documento PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Documento do Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Apresentação PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Planilha do Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Documento do Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Planilha do Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Apresentação do Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Desenho do Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabela do Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulário do Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa do Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Site do Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Pasta"</string>
+</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 3ee2c03..af691a1 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Compactar"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extrair para…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Renomear"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Propriedades"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Ver informações"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Ver em <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nova janela"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Recortar"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mover"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Dispensar"</string>
<string name="button_retry" msgid="4011461781916631389">"Tentar novamente"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Limpar"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Mostrar no provedor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sem classificação"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nome"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Resumo"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tipo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Tamanho"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Modificação"</string>
- <string name="directory_children" msgid="8115290268549503262">"Número de filhos"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Número de itens"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Crescente"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Decrescente"</string>
<string name="drawer_open" msgid="8071673398187261741">"Mostrar raízes"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Não é possível abrir o arquivo"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Não é possível abrir itens arquivados"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Não foi possível excluir alguns documentos"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Não foi possível carregar as propriedades"</string>
<string name="share_via" msgid="8725082736005677161">"Compartilhar via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Copiando arquivos"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Compactando arquivos"</string>
diff --git a/res/values-ro/inspector_strings.xml b/res/values-ro/inspector_strings.xml
new file mode 100644
index 0000000..f37e07c
--- /dev/null
+++ b/res/values-ro/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informații"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Informațiile despre fișier nu au putut fi încărcate"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informații remediere (numai pentru dezvoltatori)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadate brute: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detalii despre conținutul media"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Acest tip de fișier se deschide cu"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Acest fișier este furnizat de"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nu ați selectat"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Necunoscut"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Dimensiuni"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Coordonate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitudine"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera foto"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Diafragmă"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Viteza de declanșare"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Durată"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Realizată pe"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Distanța focală"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Echivalent ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Compozitor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Locație"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Tipuri de flux"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Dimensiune brută (octeți)"</string>
+</resources>
diff --git a/res/values-ro/mimes.xml b/res/values-ro/mimes.xml
new file mode 100644
index 0000000..fdebbb6
--- /dev/null
+++ b/res/values-ro/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Fișier <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fișier"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imagine"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imagine <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Conținut audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Videoclip"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Fișier video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arhivă <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplicaţie Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Text simplu"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Document HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Document PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Document Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Prezentare PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Foaie de calcul Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Document Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Foaie de calcul Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Prezentare Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Desen Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabel Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formular Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Hartă Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Site Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Dosar"</string>
+</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 3ac2a54..c14d37f 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Comprimați"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extrageți în…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Redenumiți"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Proprietăți"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Obțineți informații"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Afișați în <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Fereastră nouă"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Decupați"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Mutați"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Închideți"</string>
<string name="button_retry" msgid="4011461781916631389">"Încercați din nou"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Ștergeți"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Afișați în furnizor"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nesortate"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nume"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Rezumat"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tip"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Dimensiune"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Ultima modificare"</string>
- <string name="directory_children" msgid="8115290268549503262">"Număr de copii"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Numărul de articole"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"În ordine crescătoare"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"În ordine descrescătoare"</string>
<string name="drawer_open" msgid="8071673398187261741">"Afișați directoarele rădăcină"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Fișierul nu poate fi deschis"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Nu se pot deschide fișierele în arhive"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Anumite documente nu au putut fi șterse"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Proprietățile nu au putut fi încărcate"</string>
<string name="share_via" msgid="8725082736005677161">"Trimiteți prin"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Se copiază fișierele"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Se comprimă fișierele"</string>
diff --git a/res/values-ru/inspector_strings.xml b/res/values-ru/inspector_strings.xml
new file mode 100644
index 0000000..614b3fa
--- /dev/null
+++ b/res/values-ru/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Информация"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Не удалось загрузить сведения о файле"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Сведения об отладке (только для разработчиков)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Исходные метаданные: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Медиаданные"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"В каком приложении открываются файлы этого типа"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Где находится файл"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Не выбрано"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Неизвестное приложение"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Размер"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> (<xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Мпикс.)"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координаты"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Высота"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Диафрагма"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Выдержка"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Продолжительность"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Дата съемки"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Фокусное расстояние"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> мм"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Эквивалент ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Исполнитель"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Композитор"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Альбом"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Место съемки"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Типы потоков"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Исходный размер (в байтах)"</string>
+</resources>
diff --git a/res/values-ru/mimes.xml b/res/values-ru/mimes.xml
new file mode 100644
index 0000000..55e9d8d
--- /dev/null
+++ b/res/values-ru/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Файл <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Файл"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Изображение"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Изображение <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аудиофайл"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Аудиофайл <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Видео"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Видео <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Архив <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Приложение Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Обычный текст"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-документ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Документ PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Документ Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Презентация PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Таблица Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Документ Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Таблица Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Презентация Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Рисунок Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Таблица Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Форма Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Карта Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Сайт на платформе Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Папка"</string>
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index c776240..6778c9f 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Сжать"</string>
<string name="menu_extract" msgid="8171946945982532262">"Извлечь"</string>
<string name="menu_rename" msgid="1883113442688817554">"Переименовать"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Свойства"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Сведения о файле"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Открыть в приложении \"<xliff:g id="SOURCE">%1$s</xliff:g>\""</string>
<string name="menu_new_window" msgid="2947837751796109126">"Новое окно"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Вырезать"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Переместить"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Скрыть"</string>
<string name="button_retry" msgid="4011461781916631389">"Повторить"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Сбросить"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Открыть в приложении по умолчанию"</string>
<string name="not_sorted" msgid="7813496644889115530">"Документы не отсортированы"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Имя"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Сведения"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Тип"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Размер"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Изменено"</string>
- <string name="directory_children" msgid="8115290268549503262">"Количество дочерних элементов"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Количество объектов"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"По возрастанию"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"По убыванию"</string>
<string name="drawer_open" msgid="8071673398187261741">"Показать корневые папки"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Не удалось открыть файл"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Нельзя открывать файлы в архивах"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Не удалось удалить некоторые документы"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Не удалось загрузить свойства"</string>
<string name="share_via" msgid="8725082736005677161">"Поделиться"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Копирование файлов"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Сжатие файлов"</string>
diff --git a/res/values-si/inspector_strings.xml b/res/values-si/inspector_strings.xml
new file mode 100644
index 0000000..cbfab14
--- /dev/null
+++ b/res/values-si/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"තොරතුරු"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ගොනු තොරතුරු පූරණය කළ නොහැකි විය"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"දෝෂ නිරාකරණ තොරතුරු (සංවර්ධක පමණි)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"අමු පාරදත්ත: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"මාධ්ය විස්තර"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"මෙම ආකාරයේ ගොනුව මේ සමගින් විවෘත වේ"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"මෙම ගොනුව සපයනු ලබන්නේ"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"තෝරා නොමැත"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"නොදනී"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"මාන"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"ඛණ්ඩාංක"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"උන්නතාංශය"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"කැමරාව"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"විවරය"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"සංවාරක වේගය"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"කාල සීමාව"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ගන්නා ලද්දේ"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"නාභි දුර"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO තුල්ය"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"කලාකරු"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"සංගීතඥ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ඇල්බමය"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"ස්ථානය"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ප්රවාහ වර්ග"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"අමු තරම (බයිට්)"</string>
+</resources>
diff --git a/res/values-si/mimes.xml b/res/values-si/mimes.xml
new file mode 100644
index 0000000..b881624
--- /dev/null
+++ b/res/values-si/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ගොනුව"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ගොනුව"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"රූපය"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> රූපය"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ශ්රව්ය"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ශ්රව්ය"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"වීඩියෝව"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> වීඩියෝව"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> සංරක්ෂණය"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android යෙදුම"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"සරල පෙළ"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML ලේඛනය"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ලේඛනය"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ලේඛනය"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint ඉදිරිපත් කිරීම"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel පැතුරුම්පත"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google ලේඛනය"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google පැතුරුම්පත"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google ඉදිරිපත් කිරීම"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ඇඳීම"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google වගුව"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google පෝරමය"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google සිතියම්"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google අඩවිය"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ෆෝල්ඩරය"</string>
+</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index ead672e..e7eff9e 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"සම්පීඩනය කරන්න"</string>
<string name="menu_extract" msgid="8171946945982532262">"උපුටා ගන්න…"</string>
<string name="menu_rename" msgid="1883113442688817554">"යළි නම් කරන්න"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"ගුණාංග"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"තොරතුරු ලබා ගන්න"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> තුළ බලන්න"</string>
<string name="menu_new_window" msgid="2947837751796109126">"නව කවුළුව"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"කපන්න"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ගෙන යන්න"</string>
<string name="button_dismiss" msgid="7235249361023803349">"අස් කරන්න"</string>
<string name="button_retry" msgid="4011461781916631389">"නැවත උත්සාහ කරන්න"</string>
+ <string name="button_clear" msgid="5412304437764369441">"හිස් කරන්න"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"සැපයුම්කරු තුළ පෙන්වන්න"</string>
<string name="not_sorted" msgid="7813496644889115530">"අනුපිළිවෙළට සකසා නැත"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"නම"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"සාරාංශය"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"වර්ගය"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"තරම"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"වෙනස් කළේ"</string>
- <string name="directory_children" msgid="8115290268549503262">"ළමයින් ගණන"</string>
+ <string name="directory_items" msgid="6645621978998614003">"අයිතම ගණන:"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ආරෝහණ"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"අවරෝහණ"</string>
<string name="drawer_open" msgid="8071673398187261741">"මුල් පෙන්වන්න"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ගොනුව විවෘත කළ නොහැකිය"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"සංරක්ෂිත තුළ ඇති ගොනු විවෘත කළ නොහැකිය"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"සමහර ලේඛන මැකීමට නොහැකිය"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"ගුණාංග පූරණය කිරීමට නොහැකි විය"</string>
<string name="share_via" msgid="8725082736005677161">"බෙදාගන්නේ"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ගොනු පිටපත් කරමින්"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ගොනු සම්පීඩනය කරමින්"</string>
diff --git a/res/values-sk/inspector_strings.xml b/res/values-sk/inspector_strings.xml
new file mode 100644
index 0000000..d187051
--- /dev/null
+++ b/res/values-sk/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informácie"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Informácie o súbore sa nepodarilo načítať"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informácie o ladení (iba pre vývojárov)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Nespracované metadáta: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Podrobnosti o médiách"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Tento typ súboru sa otvára v aplikácii"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Poskytovateľ tohto súboru:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Nie je vybraná"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Neznáme"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Rozmery"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MPx"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Súradnice"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Nadmorská výška"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Fotoaparát"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Clona"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Rýchlosť uzávierky"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Trvanie"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Nasnímané"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Ohnisková vzdialenosť"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Ekvivalent ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Interpret"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Skladateľ"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Poloha"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Typy streamu"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Nespracovaná veľkosť (v bajtoch)"</string>
+</resources>
diff --git a/res/values-sk/mimes.xml b/res/values-sk/mimes.xml
new file mode 100644
index 0000000..5f5da5e
--- /dev/null
+++ b/res/values-sk/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Súbor <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Súbor"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Obrázok"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Obrázok <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Zvuk"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Zvuk <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Archív <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplikácia Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Obyčajný text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Dokument HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Dokument PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Dokument Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Prezentácia PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Tabuľka Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Dokument Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Tabuľka Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Prezentácia Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Nákres Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabuľka Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formulár Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Web Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Priečinok"</string>
+</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index e2ce01a..f145c9a 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Komprimovať"</string>
<string name="menu_extract" msgid="8171946945982532262">"Rozbaliť do…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Premenovať"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Vlastnosti"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Zobraziť informácie"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Zobraziť v službe <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nové okno"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Vystrihnúť"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Presunúť"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Odmietnuť"</string>
<string name="button_retry" msgid="4011461781916631389">"Skúsiť znova"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Vymazať"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Zobraziť u poskytovateľa"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nezoradené"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Názov"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Súhrn"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Typ"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Veľkosť"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Upravené"</string>
- <string name="directory_children" msgid="8115290268549503262">"Počet detí"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Počet položiek"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Vzostupne"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Zostupne"</string>
<string name="drawer_open" msgid="8071673398187261741">"Zobraziť korene"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Súbor nie je možné otvoriť"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Súbory sa nedajú otvoriť v archívoch"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Niektoré dokumenty sa nepodarilo odstrániť"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Vlastníctva sa nepodarilo načítať"</string>
<string name="share_via" msgid="8725082736005677161">"Zdieľať prostredníctvom"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopírovanie súborov"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Komprimujú sa súbory"</string>
diff --git a/res/values-sl/inspector_strings.xml b/res/values-sl/inspector_strings.xml
new file mode 100644
index 0000000..94ff443
--- /dev/null
+++ b/res/values-sl/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Podatki"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Podatkov o datoteki ni bilo mogoče naložiti"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Podatki za odpravljanje napak (samo za razvijalce)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Neobdelani metapodatki: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Podrobnosti o predstavnosti"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Za odpiranje te vrste datoteke se uporablja"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"To datoteko je posredoval"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Ni izbrano"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Neznano"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Mere"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Višina"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Fotoaparat"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Zaslonka"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Hitrost zaslonke"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Trajanje"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Posneto"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Goriščna razdalja"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Ekvivalent ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Izvajalec"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Skladatelj"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokacija"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Vrste toka"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Neobdelana velikost (bajti)"</string>
+</resources>
diff --git a/res/values-sl/mimes.xml b/res/values-sl/mimes.xml
new file mode 100644
index 0000000..1428e27
--- /dev/null
+++ b/res/values-sl/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Datoteka <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Datoteka"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Slika"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Slika <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Zvočna datoteka"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Zvočna datoteka <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arhiv <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplikacija za Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Navadno besedilo"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Dokument HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Dokument PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Wordov dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPointova predstavitev"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excelova preglednica"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Googlov dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Googlova preglednica"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Googlova predstavitev"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Googlova risba"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Googlova tabela"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Googlov obrazec"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Googlov zemljevid"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Googlovo spletno mesto"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mapa"</string>
+</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 0b43dbe..d462cbe 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Stisni"</string>
<string name="menu_extract" msgid="8171946945982532262">"Razširi v …"</string>
<string name="menu_rename" msgid="1883113442688817554">"Preimenuj"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Lastnosti"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Prikaži informacije"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Prikaži v aplikaciji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Novo okno"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Izreži"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Premakni"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Opusti"</string>
<string name="button_retry" msgid="4011461781916631389">"Poskusi znova"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Izbriši"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Prikaži na izvorni lokaciji"</string>
<string name="not_sorted" msgid="7813496644889115530">"Ni razvrščeno"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Ime"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Povzetek"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Vrsta"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Velikost"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Spremenjeno"</string>
- <string name="directory_children" msgid="8115290268549503262">"Število otrok"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Število elementov"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Naraščajoče"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Padajoče"</string>
<string name="drawer_open" msgid="8071673398187261741">"Pokaži korene"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Datoteke ni mogoče odpreti"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Datotek ni mogoče odpreti v arhivih"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Nekaterih dokumentov ni mogoče izbrisati"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Lastnosti ni bilo mogoče naložiti"</string>
<string name="share_via" msgid="8725082736005677161">"Deli z drugimi prek"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopiranje datotek"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Stiskanje datotek"</string>
diff --git a/res/values-sq/inspector_strings.xml b/res/values-sq/inspector_strings.xml
new file mode 100644
index 0000000..2ab36dc
--- /dev/null
+++ b/res/values-sq/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Informacione"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Informacioni i skedarit nuk mund të ngarkohej"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Informacioni i korrigjimit (vetëm zhvilluesit)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Të dhënat meta të papërpunuara: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Detajet e medias"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ky lloj skedari hapet me"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Ky skedar ofrohet nga"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"I pazgjedhur"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"I panjohur"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Përmasat"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinatat"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Lartësia"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Hapja e diafragmës"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Shpejtësia e obturatorit"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Kohëzgjatja"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Shkrepur në"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Gjatësia fokale"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekuivalente"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artisti"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Kompozitori"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albumi"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Vendndodhja"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Llojet e transmetimit"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Madhësia e papërpunuar (bajte)"</string>
+</resources>
diff --git a/res/values-sq/mimes.xml b/res/values-sq/mimes.xml
new file mode 100644
index 0000000..915eb17
--- /dev/null
+++ b/res/values-sq/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Skedar <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Skedar"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Imazh"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Imazh <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Audio <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Arkiv <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Aplikacion i Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Tekst i thjeshtë"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Dokument HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Dokument PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Dokument Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Prezantim PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Fletëllogaritëse Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Dokument i Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Fletëllogaritëse e Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Prezantim i Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Vizatim i Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Tabelë e Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Formular i Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Hartë e Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Sajt i Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Dosje"</string>
+</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index f1f1478..3e31507 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Ngjish"</string>
<string name="menu_extract" msgid="8171946945982532262">"Nxirre te…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Riemërto"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Karakteristikat"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Merr informacione"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Shikoje në <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Dritare e re"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Prit"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Lëviz"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Hiqe"</string>
<string name="button_retry" msgid="4011461781916631389">"Provo përsëri"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Pastro"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Shfaq te ofruesi"</string>
<string name="not_sorted" msgid="7813496644889115530">"Nuk janë të renditura"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Emri"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Përmbledhja"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Lloji"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Madhësia"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"U modifikua"</string>
- <string name="directory_children" msgid="8115290268549503262">"Numri i fëmijëve"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Numri i artikujve"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Në rritje"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Në zbritje"</string>
<string name="drawer_open" msgid="8071673398187261741">"Trego rrënjët"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Skedari nuk mund të hapet"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Skedarët në arkiva nuk mund të hapen"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"E pamundur të fshihen disa dokumente"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Karakteristikat nuk mund të ngarkoheshin"</string>
<string name="share_via" msgid="8725082736005677161">"Shpërnda nëpërmjet"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Po kopjon skedarët"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Skedarët po ngjishen"</string>
diff --git a/res/values-sr/inspector_strings.xml b/res/values-sr/inspector_strings.xml
new file mode 100644
index 0000000..c5d9aff
--- /dev/null
+++ b/res/values-sr/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Информације"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Учитавање података о датотеци није успело"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Подаци о отклањању грешака (само за програмере)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Метаподаци RAW датотеке: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Детаљи о медијима"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ова врста датотеке се отвара помоћу:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Ову датотеку пружа"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Није изабрано"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Непознато"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Димензије"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g>×<xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> мегапиксела"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координате"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Надморска висина"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Отвор бленде"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Брзина затварача"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Трајање"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Снимљено"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Жижна даљина"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO еквивалент"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Извођач"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Композитор"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Албум"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Локација"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Типови стримова"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Величина RAW датотеке (у бајтовима)"</string>
+</resources>
diff --git a/res/values-sr/mimes.xml b/res/values-sr/mimes.xml
new file mode 100644
index 0000000..f810e4a
--- /dev/null
+++ b/res/values-sr/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> датотека"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Датотека"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Слика"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> слика"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аудио"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> аудио"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Видео"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> видео"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> архива"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android апликација"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Обичан текст"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML документ"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF документ"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word документ"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint презентација"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel табела"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google документ"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google табела"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google презентација"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google цртеж"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google табела"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google упитник"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google мапа"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google сајт"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Директоријум"</string>
+</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index ded0fb6..a36c3eb 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Компримуј"</string>
<string name="menu_extract" msgid="8171946945982532262">"Издвој у…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Преименуј"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Својства"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Прикажи информације"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Прикажи у: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Нови прозор"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Исеци"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Премести"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Одбаци"</string>
<string name="button_retry" msgid="4011461781916631389">"Пробај поново"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Обриши"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Прикажи у апликацији добављача"</string>
<string name="not_sorted" msgid="7813496644889115530">"Нису сортирани"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Назив"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Резиме"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Тип"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Величина"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Измењено"</string>
- <string name="directory_children" msgid="8115290268549503262">"Број деце"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Број ставки"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Растуће"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Опадајуће"</string>
<string name="drawer_open" msgid="8071673398187261741">"Прикажи основне директоријуме"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Отварање датотеке није успело"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Не можете да отварате датотеке у архивама"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Није могуће избрисати неке документе"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Учитавање својстава није успело"</string>
<string name="share_via" msgid="8725082736005677161">"Дељење преко"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Копирамо датотеке"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Датотеке се компримују"</string>
diff --git a/res/values-sv/inspector_strings.xml b/res/values-sv/inspector_strings.xml
new file mode 100644
index 0000000..bb15919
--- /dev/null
+++ b/res/values-sv/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Information"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Det gick inte att läsa in filinformationen"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Felsökningsinformation (endast utvecklare)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Rå metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Medieuppgifter"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Den här filtypen öppnas med"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Den här filen tillhandahålls av"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Ingen har valts"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Okänd"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Mått"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinater"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Höjd"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Bländare"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Slutarhastighet"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Varaktighet"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Taget den"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Brännvidd"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO-motsvarighet"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Kompositör"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Plats"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Flödestyper"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Råstorlek (byte)"</string>
+</resources>
diff --git a/res/values-sv/mimes.xml b/res/values-sv/mimes.xml
new file mode 100644
index 0000000..a6b73ba
--- /dev/null
+++ b/res/values-sv/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g>-fil"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fil"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Bild"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g>-bild"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Ljud"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g>-ljud"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g>-video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g>-arkiv"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android-app"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Oformaterad text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML-dokument"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF-dokument"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word-dokument"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint-presentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel-kalkylark"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-dokument"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-kalkylark"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-presentation"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-teckning"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-tabell"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-formulär"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-karta"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-webbplats"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Mapp"</string>
+</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 107c2a4..7eab784 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Komprimera"</string>
<string name="menu_extract" msgid="8171946945982532262">"Extrahera till …"</string>
<string name="menu_rename" msgid="1883113442688817554">"Byt namn"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Egenskaper"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Hämta information"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Visa i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Nytt fönster"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Klipp ut"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Flytta"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ta bort"</string>
<string name="button_retry" msgid="4011461781916631389">"Försök igen"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Ta bort"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Visa hos leverantören"</string>
<string name="not_sorted" msgid="7813496644889115530">"Inte sorterade"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Namn"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Översikt"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Filtyp"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Storlek"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Ändrades senast"</string>
- <string name="directory_children" msgid="8115290268549503262">"Antal barn"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Antal objekt"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Stigande"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Fallande"</string>
<string name="drawer_open" msgid="8071673398187261741">"Visa rötter"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Det går inte att öppna filen"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Det går inte att öppna filer i arkiv"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Det gick inte att radera vissa dokument"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Det gick inte att läsa in egenskaper"</string>
<string name="share_via" msgid="8725082736005677161">"Dela via"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kopierar filer"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Filerna komprimeras"</string>
diff --git a/res/values-sw/inspector_strings.xml b/res/values-sw/inspector_strings.xml
new file mode 100644
index 0000000..d6d8e37
--- /dev/null
+++ b/res/values-sw/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Maelezo"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Imeshindwa kupakia maelezo ya faili"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Maelezo ya utatuzi (usanidi pekee)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadata ghafi: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Maelezo ya faili"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Aina hii ya faili inafunguka kwa kutumia"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Faili hii imetoka kwenye"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Haijachaguliwa"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Haijulikani"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Vipimo"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"MP <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Maeneo"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Mwinuko"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Kitundu cha kamera"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Kasi ya kilango cha kamera"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Muda"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Ilipigwa"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Urefu wa fokasi"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"mm <xliff:g id="LENGTH">%1$.2f </xliff:g>"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Inayolingana na ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Msanii"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Mtunzi"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albamu"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Mahali"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Aina za mipasho"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Ukubwa wa faili ghafi (baiti)"</string>
+</resources>
diff --git a/res/values-sw/mimes.xml b/res/values-sw/mimes.xml
new file mode 100644
index 0000000..e24a7f2
--- /dev/null
+++ b/res/values-sw/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Faili ya <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Faili"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Picha"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Picha ya <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Sauti"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Faili ya sauti ya <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video ya <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Faili ya kumbukumbu ya <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Programu ya Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Maandishi pekee"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Hati ya HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Hati ya PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Hati ya Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Wasilisho la PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Lahajedwali la Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Hati ya Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Lahajedwali la Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Wasilisho la Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Mchoro wa Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Jedwali la Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Fomu ya Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Ramani ya Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Tovuti ya Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folda"</string>
+</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 73ffd27..5063641 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Bana"</string>
<string name="menu_extract" msgid="8171946945982532262">"Weka kwenye…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Badilisha jina"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Sifa"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Pata maelezo zaidi"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Angalia katika <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Dirisha jipya"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Kata"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Hamisha"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Ondoa"</string>
<string name="button_retry" msgid="4011461781916631389">"Jaribu Tena"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Futa"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Onyesha kwenye programu ya mtoa huduma"</string>
<string name="not_sorted" msgid="7813496644889115530">"Hazijapangwa"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Jina"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Muhtasari"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Aina"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Ukubwa"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Ilibadilishwa"</string>
- <string name="directory_children" msgid="8115290268549503262">"Idadi ya Watoto"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Idadi ya vipengee"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Kupanga kwa kupanda"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Kupanga kwa kushuka"</string>
<string name="drawer_open" msgid="8071673398187261741">"Onyesha nyenzo"</string>
@@ -82,11 +84,10 @@
<string name="toast_no_application" msgid="7555319548595113121">"Haiwezi kufungua faili"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Haiwezi kufungua faili zilizo kwenye kumbukumbu"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Imeshindwa kufuta baadhi ya hati"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Imeshindwa kupakia vipengee vya faili"</string>
<string name="share_via" msgid="8725082736005677161">"Shiriki kupitia"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Inanakili faili"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Inabana faili"</string>
- <string name="extract_notification_title" msgid="5067393961754430469">"Inatoa faili"</string>
+ <string name="extract_notification_title" msgid="5067393961754430469">"Faili zinatolewa"</string>
<string name="move_notification_title" msgid="3173424987049347605">"Inahamisha faili"</string>
<string name="delete_notification_title" msgid="2512757431856830792">"Inafuta faili"</string>
<string name="copy_remaining" msgid="5390517377265177727">"Zimesalia <xliff:g id="DURATION">%s</xliff:g>"</string>
@@ -99,8 +100,8 @@
<item quantity="one">Inabana faili <xliff:g id="COUNT_0">%1$d</xliff:g>.</item>
</plurals>
<plurals name="extract_begin" formatted="false" msgid="1006380679562903749">
- <item quantity="other">Inatoa faili <xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
- <item quantity="one">Inatoa faili <xliff:g id="COUNT_0">%1$d</xliff:g>.</item>
+ <item quantity="other">Faili <xliff:g id="COUNT_1">%1$d</xliff:g> zinatolewa.</item>
+ <item quantity="one">Faili <xliff:g id="COUNT_0">%1$d</xliff:g> inatolewa.</item>
</plurals>
<plurals name="move_begin" formatted="false" msgid="1464229874265756956">
<item quantity="other">Inahamisha vipengee <xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
@@ -133,7 +134,7 @@
<item quantity="other">Imeshindwa kufuta vipengee <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Imeshindwa kufuta kipengee <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="notification_touch_for_details" msgid="2385563502445129570">"Gonga ili uangalie maelezo"</string>
+ <string name="notification_touch_for_details" msgid="2385563502445129570">"Gusa ili uangalie maelezo"</string>
<string name="close" msgid="905969391788869975">"Funga"</string>
<plurals name="copy_failure_alert_content" formatted="false" msgid="5570549471912990536">
<item quantity="other">Haikunakili faili hizi: <xliff:g id="LIST_1">%1$s</xliff:g></item>
@@ -203,6 +204,6 @@
<string name="cant_display_content" msgid="8633226333229417237">"Imeshindwa kuonyesha maudhui"</string>
<string name="sign_in" msgid="6253762676723505592">"Ingia katika akaunti"</string>
<string name="new_archive_file_name" msgid="1604650338077249838">"weka <xliff:g id="EXTENSION">%s</xliff:g> kwenye kumbukumbu"</string>
- <string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"Ungependa kufuta <xliff:g id="NAME">%1$s</xliff:g>?"</string>
+ <string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"Ungependa kubadili <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="continue_in_background" msgid="1974214559047793331">"Endelea shughuli chini chini"</string>
</resources>
diff --git a/res/values-ta/inspector_strings.xml b/res/values-ta/inspector_strings.xml
new file mode 100644
index 0000000..41bad8a
--- /dev/null
+++ b/res/values-ta/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"தகவல்"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"கோப்புத் தகவலை ஏற்ற முடியவில்லை"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"பிழைத்திருத்தத் தகவல் (டெவெலப்பர்கள் மட்டும்)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"அசல் மீத்தரவு: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"மீடியா விவரங்கள்"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"இந்தக் கோப்பு வகையை, பின்வரும் பயன்பாடு திறக்கும்:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"இந்தக் கோப்பை வழங்குவது:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"தேர்ந்தெடுக்கவில்லை"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"தெரியாதது"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"பரிமாணங்கள்"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"ஆயத்தொலைவுகள்"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"உயரம்"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"கேமரா"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"அபெர்ச்சர்"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ஷட்டர் வேகம்"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"கால அளவு"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"படமெடுத்தது:"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"குவியத்தூரம்"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>மிமீ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO சமதிறன்"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"கலைஞர்"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"இசையமைப்பாளர்"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ஆல்பம்"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"இருப்பிடம்"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ஸ்ட்ரீம் வகைகள்"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"அசல் அளவு (பைட்டுகள்)"</string>
+</resources>
diff --git a/res/values-ta/mimes.xml b/res/values-ta/mimes.xml
new file mode 100644
index 0000000..04a8c3f
--- /dev/null
+++ b/res/values-ta/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> கோப்பு"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"கோப்பு"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"படம்"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> படம்"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ஆடியோ"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ஆடியோ"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"வீடியோ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> வீடியோ"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> காப்பகம்"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android பயன்பாடு"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"எளிய உரை"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML ஆவணம்"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF ஆவணம்"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word ஆவணம்"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint விளக்கக்காட்சி"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel விரிதாள்"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google ஆவணம்"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google விரிதாள்"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google விளக்கக்காட்சி"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google டிராயிங்"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google அட்டவணை"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google படிவம்"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google வரைபடம்"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google தளம்"</string>
+ <string name="directory_type" msgid="2702987727566226354">"கோப்புறை"</string>
+</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 1090358..cac3838 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="files_label" msgid="771781190045103748">"கோப்புகள்"</string>
+ <string name="files_label" msgid="771781190045103748">"ஃபைல்கள்"</string>
<string name="downloads_label" msgid="5462789470049501103">"இறக்கங்கள்"</string>
<!-- no translation found for app_label (8089292432455111409) -->
<skip />
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"அளவைக் குறை"</string>
<string name="menu_extract" msgid="8171946945982532262">"இங்கு பிரி…"</string>
<string name="menu_rename" msgid="1883113442688817554">"மறுபெயரிடு"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"பண்புகள்"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"தகவலைப் பெறு"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> இல் காட்டு"</string>
<string name="menu_new_window" msgid="2947837751796109126">"புதிய சாளரம்"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"வெட்டு"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"நகர்த்து"</string>
<string name="button_dismiss" msgid="7235249361023803349">"நிராகரி"</string>
<string name="button_retry" msgid="4011461781916631389">"மீண்டும் முயலவும்"</string>
+ <string name="button_clear" msgid="5412304437764369441">"அழி"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"வழங்குநரில் காட்டு"</string>
<string name="not_sorted" msgid="7813496644889115530">"வரிசைப்படுத்தப்படவில்லை"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"பெயர்"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"சுருக்க விவரம்"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"வகை"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"அளவு"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"மாற்றியது"</string>
- <string name="directory_children" msgid="8115290268549503262">"குழந்தைகளின் எண்ணிக்கை"</string>
+ <string name="directory_items" msgid="6645621978998614003">"உருப்படிகளின் எண்ணிக்கை"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ஏறுவரிசையில்"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"இறங்குவரிசையில்"</string>
<string name="drawer_open" msgid="8071673398187261741">"சேமித்த இடத்தைக் காட்டு"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"கோப்பைத் திறக்க முடியாது"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"காப்பகங்களில் உள்ள கோப்புகளைத் திறக்க முடியாது"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"சில ஆவணங்களை நீக்க முடியவில்லை"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"பண்புகளை ஏற்ற முடியவில்லை"</string>
<string name="share_via" msgid="8725082736005677161">"இதன் வழியாகப் பகிர்"</string>
<string name="copy_notification_title" msgid="52256435625098456">"கோப்புகளை நகலெடுத்தல்"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"அளவைக் குறைக்கிறது"</string>
diff --git a/res/values-te/inspector_strings.xml b/res/values-te/inspector_strings.xml
new file mode 100644
index 0000000..97dd812
--- /dev/null
+++ b/res/values-te/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"సమాచారం"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ఫైల్ సమాచారాన్ని లోడ్ చేయడం సాధ్యపడలేదు"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"డీబగ్ సమాచారం (డెవలపర్ మాత్రమే)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"ప్రాసెస్ చేయని మెటాడేటా: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"మీడియా వివరాలు"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ఈ రకమైన ఫైల్ దీనితో తెరవబడుతుంది"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ఇది ఈ ఫైల్ని అందించింది"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"ఎంచుకోబడలేదు"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"తెలియదు"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"కొలతలు"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"అక్షాంశాలు"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ఎత్తు"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"కెమెరా"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"ఎపర్చర్"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"షట్టర్ వేగం"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"వ్యవధి"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ఫోటో ఈ తేదీన తీయబడింది"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ఫోకల్ పొడవు"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>మి.మీ"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO సమానమైనది"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"కళాకారుడు"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"కంపోజర్"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"ఆల్బమ్"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"స్థానం"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ప్రసార రకాలు"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"ప్రాసెస్ చేయని పరిమాణం (బైట్లు)"</string>
+</resources>
diff --git a/res/values-te/mimes.xml b/res/values-te/mimes.xml
new file mode 100644
index 0000000..bcbbda2
--- /dev/null
+++ b/res/values-te/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ఫైల్"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ఫైల్"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"చిత్రం"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> చిత్రం"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"ఆడియో"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ఆడియో"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"వీడియో"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> వీడియో"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> ఆర్కైవ్"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android అప్లికేషన్"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"సాదా వచనం"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML పత్రం"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF పత్రం"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word పత్రం"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint ప్రెజెంటేషన్"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel స్ప్రెడ్షీట్"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google పత్రం"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google స్ప్రెడ్షీట్"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google ప్రెజెంటేషన్"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google డ్రాయింగ్"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google పట్టిక"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ఫారమ్"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google మ్యాప్"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google సైట్"</string>
+ <string name="directory_type" msgid="2702987727566226354">"ఫోల్డర్"</string>
+</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index bc286e2..68ac482 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -27,7 +27,7 @@
<string name="menu_create_dir" msgid="2413624798689091042">"కొత్త ఫోల్డర్"</string>
<string name="menu_grid" msgid="1453636521731880680">"గ్రిడ్ వీక్షణ"</string>
<string name="menu_list" msgid="6714267452146410402">"జాబితా వీక్షణ"</string>
- <string name="menu_search" msgid="1876699106790719849">"శోధించు"</string>
+ <string name="menu_search" msgid="1876699106790719849">"వెతుకు"</string>
<string name="menu_settings" msgid="6520844520117939047">"నిల్వ సెట్టింగ్లు"</string>
<string name="menu_open" msgid="9092138100049759315">"తెరువు"</string>
<string name="menu_open_with" msgid="5507647065467520229">"దీనితో తెరువు"</string>
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"కుదించు"</string>
<string name="menu_extract" msgid="8171946945982532262">"దీనిలోకి సంగ్రహించు…"</string>
<string name="menu_rename" msgid="1883113442688817554">"పేరు మార్చు"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"లక్షణాలు"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"సమాచారాన్ని పొందండి"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g>లో వీక్షించు"</string>
<string name="menu_new_window" msgid="2947837751796109126">"కొత్త విండో"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"కత్తిరించు"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"తరలించు"</string>
<string name="button_dismiss" msgid="7235249361023803349">"తీసివేయి"</string>
<string name="button_retry" msgid="4011461781916631389">"మళ్లీ ప్రయత్నించు"</string>
+ <string name="button_clear" msgid="5412304437764369441">"తీసివేయండి"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"ప్రదాతలో చూపించండి"</string>
<string name="not_sorted" msgid="7813496644889115530">"క్రమబద్ధీకరించలేదు"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"పేరు"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"సారాంశం"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"రకం"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"పరిమాణం"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"సవరించిన సమయం"</string>
- <string name="directory_children" msgid="8115290268549503262">"పిల్లల సంఖ్య"</string>
+ <string name="directory_items" msgid="6645621978998614003">"అంశాల సంఖ్య"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"ఆరోహణ"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"అవరోహణ"</string>
<string name="drawer_open" msgid="8071673398187261741">"మూలాలను చూపు"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"ఫైల్ను తెరవడం సాధ్యపడదు"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"ఆర్కైవ్లలో ఉన్న ఫైల్లను తెరవడం సాధ్యం కాదు"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"కొన్ని పత్రాలను తొలగించడం సాధ్యపడలేదు"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"లక్షణాలను లోడ్ చేయలేకపోయింది"</string>
<string name="share_via" msgid="8725082736005677161">"దీనితో భాగస్వామ్యం చేయండి"</string>
<string name="copy_notification_title" msgid="52256435625098456">"ఫైల్లు కాపీ అవుతున్నాయి"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"ఫైల్లను కుదిస్తోంది"</string>
@@ -179,7 +180,7 @@
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ఎంచుకోబడింది</item>
</plurals>
<plurals name="elements_dragged" formatted="false" msgid="5932571296037626279">
- <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> అంశాలు</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> వస్తువులు</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> అంశం</item>
</plurals>
<string name="delete_filename_confirmation_message" msgid="8338069763240613258">"\"<xliff:g id="NAME">%1$s</xliff:g>\"ని తొలగించాలా?"</string>
diff --git a/res/values-th/inspector_strings.xml b/res/values-th/inspector_strings.xml
new file mode 100644
index 0000000..855b581
--- /dev/null
+++ b/res/values-th/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"ข้อมูล"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"ไม่สามารถโหลดข้อมูลไฟล์"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ข้อมูลการแก้ไขข้อบกพร่อง (dev only)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"ข้อมูลเมตา Raw: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"รายละเอียดสื่อ"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"ไฟล์ประเภทนี้เปิดด้วย"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"ไฟล์นี้จัดหาโดย"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"ไม่ได้เลือก"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"ไม่ทราบ"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ขนาด"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"พิกัด"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"ระดับความสูง"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"กล้อง"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"รูรับแสง"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"ความเร็วชัตเตอร์"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"ระยะเวลา"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"ถ่ายเมื่อ"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ความยาวโฟกัส"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> มม."</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO เทียบเท่า"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"ศิลปิน"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"ผู้ประพันธ์เพลง"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"อัลบั้ม"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"ตำแหน่ง"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"ประเภทสตรีม"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"ขนาด Raw (ไบต์)"</string>
+</resources>
diff --git a/res/values-th/mimes.xml b/res/values-th/mimes.xml
new file mode 100644
index 0000000..c29f40b
--- /dev/null
+++ b/res/values-th/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"ไฟล์ <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"ไฟล์"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"รูปภาพ"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"ภาพ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"เสียง"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"ไฟล์เสียง <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"วิดีโอ"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"วิดีโอ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"ไฟล์ที่เก็บถาวร <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"แอปพลิเคชัน Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"ข้อความล้วน"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"เอกสาร HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"เอกสาร PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"เอกสาร Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"งานนำเสนอ PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"สเปรดชีต Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google เอกสาร"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google สเปรดชีต"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google งานนำเสนอ"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ภาพวาด"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google ตาราง"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google ฟอร์ม"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google Map"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google Site"</string>
+ <string name="directory_type" msgid="2702987727566226354">"โฟลเดอร์"</string>
+</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index a3a85d3..b94205c 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"บีบอัด"</string>
<string name="menu_extract" msgid="8171946945982532262">"แตกข้อมูลไปยัง…"</string>
<string name="menu_rename" msgid="1883113442688817554">"เปลี่ยนชื่อ"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"คุณสมบัติ"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"รับข้อมูล"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"ดูใน <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"หน้าต่างใหม่"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"ตัด"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"ย้าย"</string>
<string name="button_dismiss" msgid="7235249361023803349">"ปิด"</string>
<string name="button_retry" msgid="4011461781916631389">"ลองใหม่"</string>
+ <string name="button_clear" msgid="5412304437764369441">"ล้าง"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"แสดงในแอปผู้ให้บริการ"</string>
<string name="not_sorted" msgid="7813496644889115530">"ไม่ได้จัดเรียง"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"ชื่อ"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"สรุป"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"ประเภท"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"ขนาด"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"แก้ไข"</string>
- <string name="directory_children" msgid="8115290268549503262">"จำนวนบุตรหลาน"</string>
+ <string name="directory_items" msgid="6645621978998614003">"จำนวนรายการ"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"จากน้อยไปมาก"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"จากมากไปน้อย"</string>
<string name="drawer_open" msgid="8071673398187261741">"แสดงราก"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"เปิดไฟล์ไม่ได้"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"เปิดไฟล์ในที่เก็บถาวรไม่ได้"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"ไม่สามารถลบเอกสารบางรายการ"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"ไม่สามารถโหลดพร็อพเพอร์ตี้"</string>
<string name="share_via" msgid="8725082736005677161">"แชร์ผ่าน"</string>
<string name="copy_notification_title" msgid="52256435625098456">"กำลังคัดลอกไฟล์"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"กำลังบีบอัดไฟล์"</string>
diff --git a/res/values-tl/inspector_strings.xml b/res/values-tl/inspector_strings.xml
new file mode 100644
index 0000000..a18fe5a
--- /dev/null
+++ b/res/values-tl/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Impormasyon"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Hindi ma-load ang impormasyon ng file"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Impormasyon ng debug (dev lang)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Raw na metadata: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Mga detalye ng media"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Nabubuksan ang ganitong uri ng file sa"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Ang file na ito ay ibinigay ng"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Hindi napili"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Hindi Alam"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Mga Dimensyon"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Mga Coordinate"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Altitude"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Camera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Aperture"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Bilis ng shutter"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Tagal"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Kinunan noong"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Focal length"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Katumbas sa ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Artist"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Composer"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Lokasyon"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Mga uri ng stream"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Raw na laki (mga byte)"</string>
+</resources>
diff --git a/res/values-tl/mimes.xml b/res/values-tl/mimes.xml
new file mode 100644
index 0000000..ecc62d8
--- /dev/null
+++ b/res/values-tl/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> na file"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"File"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Larawan"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> na larawan"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> na audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> na video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> na archive"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android application"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Plain text"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML na dokumento"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF na dokumento"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Dokumento sa Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint presentation"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Spreadsheet sa Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Dokumento sa Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Spreadsheet sa Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Presentation sa Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Drawing sa Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Talahanayan sa Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Form sa Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Mapa sa Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Site ng Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Folder"</string>
+</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 25daf25..ac28e52 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"I-compress"</string>
<string name="menu_extract" msgid="8171946945982532262">"I-extract sa…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Palitan ang pangalan"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Mga Property"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Kumuha ng impormasyon"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Tingnan sa <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Bagong window"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"I-cut"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Ilipat"</string>
<string name="button_dismiss" msgid="7235249361023803349">"I-dismiss"</string>
<string name="button_retry" msgid="4011461781916631389">"Subukang Muli"</string>
+ <string name="button_clear" msgid="5412304437764369441">"I-clear"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Ipakita sa provider"</string>
<string name="not_sorted" msgid="7813496644889115530">"Hindi napagbukud-bukod"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Pangalan"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Buod"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Uri"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Laki"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Binago"</string>
- <string name="directory_children" msgid="8115290268549503262">"Bilang ng Mga Bata"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Bilang ng mga item"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Pataas"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Pababa"</string>
<string name="drawer_open" msgid="8071673398187261741">"Ipakita ang mga root"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Hindi mabuksan ang file"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Hindi mabuksan ang mga file sa mga archive"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Hindi ma-delete ang ilang dokumento"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Hindi ma-load ang mga property"</string>
<string name="share_via" msgid="8725082736005677161">"Ibahagi gamit ang"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Kinokopya ang mga file"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Kino-compress ang files"</string>
diff --git a/res/values-tr/inspector_strings.xml b/res/values-tr/inspector_strings.xml
new file mode 100644
index 0000000..23e01c0
--- /dev/null
+++ b/res/values-tr/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Bilgi"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Dosya bilgisi yüklenemedi"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Hata ayıklama bilgileri (yalnızca geliştirici)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"İşlenmemiş meta veri: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Medya ayrıntıları"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Bu tür dosyalar şu uygulamayla açılır:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Bu dosyayı sağlayan:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Seçili değil"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Bilinmiyor"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Boyutlar"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinatlar"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Rakım"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Diyafram açıklığı"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Deklanşör hızı"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Süre"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Çekim zamanı:"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Odak uzaklığı"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO karşılığı"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Sanatçı"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Besteci"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albüm"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Konum"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Akış türleri"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"İşlenmemiş boyut (bayt)"</string>
+</resources>
diff --git a/res/values-tr/mimes.xml b/res/values-tr/mimes.xml
new file mode 100644
index 0000000..c76e0f6
--- /dev/null
+++ b/res/values-tr/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> dosyası"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Dosya"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Resim"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> resmi"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Ses"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> ses"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> videosu"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> arşivi"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android uygulaması"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Düz metin"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML dokümanı"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF dokümanı"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word dokümanı"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint sunusu"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel e-tablosu"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google dokümanı"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google e-tablosu"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google sunusu"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google çizimi"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google tablosu"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google formu"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google haritası"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google sitesi"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Klasör"</string>
+</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 46d631e..7556431 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Sıkıştır"</string>
<string name="menu_extract" msgid="8171946945982532262">"Şuraya çıkar:"</string>
<string name="menu_rename" msgid="1883113442688817554">"Yeniden Adlandır"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Özellikler"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Bilgi al"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> içinde görüntüle"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Yeni pencere"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Kes"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Taşı"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Kapat"</string>
<string name="button_retry" msgid="4011461781916631389">"Tekrar Dene"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Temizle"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Sağlayıcıda göster"</string>
<string name="not_sorted" msgid="7813496644889115530">"Sıralanmadı"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Ad"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Özet"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Tür"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Boyut"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Değiştirilme zamanı"</string>
- <string name="directory_children" msgid="8115290268549503262">"Çocuk Sayısı"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Ürün sayısı"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Artan"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Azalan"</string>
<string name="drawer_open" msgid="8071673398187261741">"Kök dizinleri göster"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Dosya açılamıyor"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Arşivlerdeki dosyalar açılamaz"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Bazı dokümanlar silinemiyor"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Özellikler yüklenemedi"</string>
<string name="share_via" msgid="8725082736005677161">"Şunu kullanarak paylaşın:"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Dosyalar kopyalanıyor"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Dosyalar sıkıştırılıyor"</string>
diff --git a/res/values-uk/inspector_strings.xml b/res/values-uk/inspector_strings.xml
new file mode 100644
index 0000000..319b598
--- /dev/null
+++ b/res/values-uk/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Інформація"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Не вдалося завантажити інформацію про файл"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Дані про налагодження (лише для розробників)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Метадані файлу RAW: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Деталі медіа-вмісту"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Цей тип файлу відкривається в додатку"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Цей файл надає"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Не вибрано"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Невідомо"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Розміри"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> Мпікс."</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Координати"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Висота"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Апертура"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Швидкість затвора"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Тривалість"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Знято"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Фокусна відстань"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> мм"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Еквівалент ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"Швидкість ISO: <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Виконавець"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Композитор"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Альбом"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Місцезнаходження"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Типи потоків"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Розмір файлу RAW (байти)"</string>
+</resources>
diff --git a/res/values-uk/mimes.xml b/res/values-uk/mimes.xml
new file mode 100644
index 0000000..e41138b
--- /dev/null
+++ b/res/values-uk/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Файл <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Файл"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Зображення"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Зображення <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Аудіо"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Аудіо <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Відео"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Відео <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Архів <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Додаток Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Звичайний текст"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Документ HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Документ PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Документ Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Презентація PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Електронна таблиця Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Документ Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Таблиця Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Презентація Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Малюнок Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Таблиця Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Форма Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Карта Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Сайт Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Папка"</string>
+</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 1a7f83e..e0d1fb0 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Стиснути"</string>
<string name="menu_extract" msgid="8171946945982532262">"Розпакувати…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Перейменувати"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Властивості"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Переглянути інформацію"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Переглянути в службі <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Нове вікно"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Вирізати"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Перемістити"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Відхилити"</string>
<string name="button_retry" msgid="4011461781916631389">"Повторити"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Очистити"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Показати в сервісі постачальника"</string>
<string name="not_sorted" msgid="7813496644889115530">"Не сортовано"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Назва"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Короткий опис"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Тип"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Розмір"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Змінено"</string>
- <string name="directory_children" msgid="8115290268549503262">"Кількість дітей"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Кількість елементів"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"За зростанням"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"За спаданням"</string>
<string name="drawer_open" msgid="8071673398187261741">"Показати кореневі каталоги"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Не вдалося відкрити файл"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Не вдалося відкрити файли в архівах"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Не вдалося видалити деякі документи"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Не вдалося завантажити параметри"</string>
<string name="share_via" msgid="8725082736005677161">"Надіслати через"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Копіювання файлів"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Файли стискаються"</string>
diff --git a/res/values-ur/inspector_strings.xml b/res/values-ur/inspector_strings.xml
new file mode 100644
index 0000000..bfe1b66
--- /dev/null
+++ b/res/values-ur/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"معلومات"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"فائل کى معلومات لوڈ نہیں کی جا سکی"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"ڈیبگ کی معلومات (ڈیولپر فقط)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"خام میٹا ڈیٹا: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"میڈیا کی تفصیلات"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"اس قسم کی فائل اس کے ساتھ کُھلتی ہے"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"یہ فائل فراہم کی جاتی ہے"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"غیر منتخب کردہ"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"نامعلوم"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"ابعاد"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"کوآرڈینیٹس"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>، <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"اونچائی"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"کیمرا"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"اپرچر"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"شٹر کی رفتار"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"مدت"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"تصویر لے لی گئی"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"ماسکہ کی طوالت"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>ملی میٹر"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO کے مساوی"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"فنکار"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"کمپوزر"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"البم"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"مقام"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"سلسلہ کی قسمیں"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"خام سائز (بائٹس)"</string>
+</resources>
diff --git a/res/values-ur/mimes.xml b/res/values-ur/mimes.xml
new file mode 100644
index 0000000..045182a
--- /dev/null
+++ b/res/values-ur/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> فائل"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"فائل"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"تصویر"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> تصویر"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"آڈیو"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> آڈیو"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"ویڈیو"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> ویڈیو"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> آرکائيو"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android ایپلیکیشن"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"سادہ متن"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML دستاویز"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF دستاویز"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word دستاویز"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint پیشکش"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel اسپریڈ شیٹ"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google دستاویز"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google اسپریڈ شیٹ"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google پیشکش"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google ڈرائنگ"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google ٹیبل"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google فارم"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google نقشہ"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google سائٹ"</string>
+ <string name="directory_type" msgid="2702987727566226354">"فولڈر"</string>
+</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 068550d..2956505 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"کمپریس کریں"</string>
<string name="menu_extract" msgid="8171946945982532262">"اس میں کھولیں۔۔۔"</string>
<string name="menu_rename" msgid="1883113442688817554">"نام تبدیل کریں"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"خصوصیات"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"معلومات حاصل کریں"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> میں دیکھیں"</string>
<string name="menu_new_window" msgid="2947837751796109126">"نئی ونڈو"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"کٹ کریں"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"منتقل کریں"</string>
<string name="button_dismiss" msgid="7235249361023803349">"کالعدم کریں"</string>
<string name="button_retry" msgid="4011461781916631389">"دوبارہ کوشش کریں"</string>
+ <string name="button_clear" msgid="5412304437764369441">"صاف کریں"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"فراہم کنندہ میں دکھائیں"</string>
<string name="not_sorted" msgid="7813496644889115530">"ترتیب میں نہیں ہیں"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"نام"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"خلاصہ"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"قسم"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"سائز"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"ترمیم ہوئی"</string>
- <string name="directory_children" msgid="8115290268549503262">"بچوں کی تعداد"</string>
+ <string name="directory_items" msgid="6645621978998614003">"آئٹمز کی تعداد"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"صعودی"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"نزولی"</string>
<string name="drawer_open" msgid="8071673398187261741">"روٹس دکھائیں"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"فائل نہیں کھل سکتی"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"فائلوں کو آرکائیوز میں کھولا نہیں جا سکتا"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"کچھ دستاویزات کو حذف کرنے سے قاصر"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"خصوصیات کو لوڈ نہیں کیا جا سکا"</string>
<string name="share_via" msgid="8725082736005677161">"اشتراک کریں بذریعہ"</string>
<string name="copy_notification_title" msgid="52256435625098456">"فائلیں کاپی ہو رہی ہیں"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"فائلز کمپریس ہو رہی ہیں"</string>
diff --git a/res/values-uz/inspector_strings.xml b/res/values-uz/inspector_strings.xml
new file mode 100644
index 0000000..1a791f3
--- /dev/null
+++ b/res/values-uz/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Ma’lumot"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Fayl haqida ma’lumotni yuklab bo‘lmadi"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Xatoliklarni tuzatish (faqat dasturchilar uchun)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"RAW fayli meta-axboroti: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Media tafsilotlari"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Bu turdagi fayl quyidagilar bilan ochiladi"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Bu fayl ta’minotchisi"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Tanlanmagan"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Noma’lum"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"O‘lchamlar"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> – <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Koordinatalari"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Dengiz sathidan balandligi"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Diafragma"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Zatvor tezligi"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Davomiyligi"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Yaratilgan sanasi"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Fokus masofasi"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO ekvivalenti"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Ijrochi"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Bastakor"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Albom"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Joylashuv"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Strim turlari"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"RAW fayl hajmi (bayt)"</string>
+</resources>
diff --git a/res/values-uz/mimes.xml b/res/values-uz/mimes.xml
new file mode 100644
index 0000000..d9a4346
--- /dev/null
+++ b/res/values-uz/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> fayl"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Fayl"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Rasm"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> rasm"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Audio"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> audio"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> video"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> arxiv"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android ilovasi"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Oddiy matn"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML hujjat"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF hujjat"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word hujjat"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint taqdimot"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel jadval"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google-hujjat"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google-jadval"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google-taqdimot"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google-chizma"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google-jadval"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google-shakl"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google-xarita"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google-sayt"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Jild"</string>
+</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 9d84a82..e221715 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -26,7 +26,7 @@
<string name="title_save" msgid="4384490653102710025">"Saqlash"</string>
<string name="menu_create_dir" msgid="2413624798689091042">"Yangi jild"</string>
<string name="menu_grid" msgid="1453636521731880680">"To‘r ko‘rinishida"</string>
- <string name="menu_list" msgid="6714267452146410402">"Ro‘yxat ko‘rinishida"</string>
+ <string name="menu_list" msgid="6714267452146410402">"Qator"</string>
<string name="menu_search" msgid="1876699106790719849">"Qidiruv"</string>
<string name="menu_settings" msgid="6520844520117939047">"Xotira sozlamalari"</string>
<string name="menu_open" msgid="9092138100049759315">"Ochish"</string>
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Arxivlash"</string>
<string name="menu_extract" msgid="8171946945982532262">"Arxivdan chiqarish"</string>
<string name="menu_rename" msgid="1883113442688817554">"Qayta nomlash"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Xususiyatlar"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Ma’lumot olish"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"<xliff:g id="SOURCE">%1$s</xliff:g> orqali ochish"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Yangi oyna"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Kesish"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Ko‘chirib o‘tkazish"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Yopish"</string>
<string name="button_retry" msgid="4011461781916631389">"Qayta urinib ko‘rish"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Tozalash"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Ta’minotchi orqali ko‘rsatish"</string>
<string name="not_sorted" msgid="7813496644889115530">"Saralanmagan"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Nomi"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Qisqacha tavsif"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Turi"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Hajmi"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Tahrirlangan"</string>
- <string name="directory_children" msgid="8115290268549503262">"Quyi elementlar soni"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Elementlar soni"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"O‘sish bo‘yicha"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Kamayish bo‘yicha"</string>
<string name="drawer_open" msgid="8071673398187261741">"Ko‘rsatish"</string>
@@ -82,8 +84,7 @@
<string name="toast_no_application" msgid="7555319548595113121">"Faylni ochib bo‘lmadi"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Arxivdagi fayllarni ochib bo‘lmadi"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Ba’zi hujjatlarni o‘chirib bo‘lmadi"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Xususiyatlarni yuklab bo‘lmadi"</string>
- <string name="share_via" msgid="8725082736005677161">"Baham ko‘rish"</string>
+ <string name="share_via" msgid="8725082736005677161">"Ulashish"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Fayllar nusxalanmoqda"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Fayllar arxivlanmoqda"</string>
<string name="extract_notification_title" msgid="5067393961754430469">"Arxivdan chiqarilmoqda"</string>
diff --git a/res/values-vi/inspector_strings.xml b/res/values-vi/inspector_strings.xml
new file mode 100644
index 0000000..c540bff
--- /dev/null
+++ b/res/values-vi/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Thông tin"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Không thể tải thông tin tệp"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Thông tin gỡ lỗi (chỉ dành cho nhà phát triển)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Siêu dữ liệu Raw: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Chi tiết về phương tiện"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Loại tệp này mở bằng"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Tệp này được cung cấp bởi"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Chưa chọn"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Không xác định"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Kích thước"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Tọa độ"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Độ cao"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Máy ảnh"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Khẩu độ"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Tốc độ chụp"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Thời lượng"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Chụp vào"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Tiêu cự"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO tương đương"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Nghệ sĩ"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Nhà soạn nhạc"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"Album"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Địa điểm"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Loại luồng"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Kích thước tệp Raw (byte)"</string>
+</resources>
diff --git a/res/values-vi/mimes.xml b/res/values-vi/mimes.xml
new file mode 100644
index 0000000..437211f
--- /dev/null
+++ b/res/values-vi/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"Tệp <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Tệp"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Hình ảnh"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"Hình ảnh <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Âm thanh"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"Âm thanh <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Video"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"Video <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"Lưu trữ <xliff:g id="FILETYPE">%1$s</xliff:g>"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Ứng dụng Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Văn bản thuần"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Tài liệu HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Tài liệu PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Tài liệu Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Bản trình bày PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Bảng tính Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Tài liệu Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Bảng tính Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Bản trình bày Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Bản vẽ Google"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Bảng Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Biểu mẫu Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Bản đồ Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Trang web Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Thư mục"</string>
+</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 4dd695d..4bce8a3 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Nén"</string>
<string name="menu_extract" msgid="8171946945982532262">"Trích xuất sang…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Đổi tên"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Thuộc tính"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Xem thông tin"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Xem trong <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Cửa sổ mới"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Cắt"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Chuyển"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Loại bỏ"</string>
<string name="button_retry" msgid="4011461781916631389">"Thử lại"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Xóa"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Hiển thị trong nhà cung cấp"</string>
<string name="not_sorted" msgid="7813496644889115530">"Chưa được sắp xếp"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Tên"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Tóm tắt"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Loại"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Kích thước"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Đã sửa đổi"</string>
- <string name="directory_children" msgid="8115290268549503262">"Số trẻ em"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Số mục"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Tăng dần"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Giảm dần"</string>
<string name="drawer_open" msgid="8071673398187261741">"Hiển thị gốc"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Không thể mở tệp"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Không thể mở tệp trong lưu trữ"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Không thể xóa một số tài liệu"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Không thể tải các thuộc tính"</string>
<string name="share_via" msgid="8725082736005677161">"Chia sẻ qua"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Đang sao chép tệp"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Nén tệp"</string>
diff --git a/res/values-zh-rCN/inspector_strings.xml b/res/values-zh-rCN/inspector_strings.xml
new file mode 100644
index 0000000..312f3db
--- /dev/null
+++ b/res/values-zh-rCN/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"信息"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"无法加载文件信息"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"调试信息(仅限开发者)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"原始元数据:<xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"媒体详情"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"使用以下应用打开这类文件:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"此文件的提供方:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"未选择"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"未知"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"尺寸"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> 百万像素"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"坐标"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>,<xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"海拔"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"相机"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"光圈"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"快门速度"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"时长"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"拍摄时间"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"焦距"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> 毫米"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO 等效感光度"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"音乐人"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"作曲家"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"专辑"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"位置"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"流式传输类型"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"原始大小(字节)"</string>
+</resources>
diff --git a/res/values-zh-rCN/mimes.xml b/res/values-zh-rCN/mimes.xml
new file mode 100644
index 0000000..eb3a6c1
--- /dev/null
+++ b/res/values-zh-rCN/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> 文件"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"文件"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"图片"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> 图片"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"音频"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> 音频"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"视频"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> 视频"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> 归档文件"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android 应用"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"纯文本"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML 文档"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF 文档"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word 文档"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint 演示文稿"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel 电子表格"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google 文档"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google 电子表格"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google 演示文稿"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google 绘图"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google 表格"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google 表单"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google 地图"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google 网站"</string>
+ <string name="directory_type" msgid="2702987727566226354">"文件夹"</string>
+</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 1aec392..cb990eb 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"压缩"</string>
<string name="menu_extract" msgid="8171946945982532262">"解压到…"</string>
<string name="menu_rename" msgid="1883113442688817554">"重命名"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"属性"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"获取信息"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"在“<xliff:g id="SOURCE">%1$s</xliff:g>”中查看"</string>
<string name="menu_new_window" msgid="2947837751796109126">"新建窗口"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"剪切"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"移动"</string>
<string name="button_dismiss" msgid="7235249361023803349">"关闭"</string>
<string name="button_retry" msgid="4011461781916631389">"重试"</string>
+ <string name="button_clear" msgid="5412304437764369441">"清除"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"在提供程序中显示"</string>
<string name="not_sorted" msgid="7813496644889115530">"未排序"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"名称"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"摘要"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"类型"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"大小"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"上次修改时间"</string>
- <string name="directory_children" msgid="8115290268549503262">"儿童人数"</string>
+ <string name="directory_items" msgid="6645621978998614003">"项数"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"升序"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"降序"</string>
<string name="drawer_open" msgid="8071673398187261741">"显示根目录"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"无法打开文件"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"无法打开归档文件"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"无法删除部分文档"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"无法加载属性"</string>
<string name="share_via" msgid="8725082736005677161">"分享方式"</string>
<string name="copy_notification_title" msgid="52256435625098456">"正在复制文件"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"正在压缩文件"</string>
diff --git a/res/values-zh-rHK/inspector_strings.xml b/res/values-zh-rHK/inspector_strings.xml
new file mode 100644
index 0000000..8b7e48f
--- /dev/null
+++ b/res/values-zh-rHK/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"資訊"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"無法載入檔案資訊"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"偵錯資料 (只限開發人員)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"原始元數據:<xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"媒體詳情"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"使用以下應用程式開啟這種檔案:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"這個檔案的提供者:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"未選取"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"不明"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"尺寸"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> 百萬像素"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"座標"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>,<xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"高度"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"相機"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"光圈"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"快門速度"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"時間長度"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"拍攝時間"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"焦距"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> 毫米"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"ISO 等效感光度"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"歌手"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"作曲者"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"專輯"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"位置"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"串流類型"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"原始大小 (字節)"</string>
+</resources>
diff --git a/res/values-zh-rHK/mimes.xml b/res/values-zh-rHK/mimes.xml
new file mode 100644
index 0000000..d250e18
--- /dev/null
+++ b/res/values-zh-rHK/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> 檔案"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"檔案"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"圖片"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> 圖片"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"音訊"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> 音訊"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"影片"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> 影片"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> 封存檔案"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android 應用程式"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"純文字"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML 文件"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF 文件"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word 文件"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint 簡報"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel 試算表"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google 文件"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google 試算表"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google 簡報"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google 繪圖"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google 表格"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google 表格"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google 地圖"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google 網站"</string>
+ <string name="directory_type" msgid="2702987727566226354">"資料夾"</string>
+</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 399f1d0..67d3e6a 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"壓縮"</string>
<string name="menu_extract" msgid="8171946945982532262">"壓縮至…"</string>
<string name="menu_rename" msgid="1883113442688817554">"重新命名"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"屬性"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"顯示資訊"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"在「<xliff:g id="SOURCE">%1$s</xliff:g>」中查看"</string>
<string name="menu_new_window" msgid="2947837751796109126">"新視窗"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"剪下"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"移動"</string>
<string name="button_dismiss" msgid="7235249361023803349">"關閉"</string>
<string name="button_retry" msgid="4011461781916631389">"再試一次"</string>
+ <string name="button_clear" msgid="5412304437764369441">"清除"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"在供應商的應用程式中顯示"</string>
<string name="not_sorted" msgid="7813496644889115530">"尚未排序"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"名稱"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"摘要"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"類型"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"大小"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"上次修改時間"</string>
- <string name="directory_children" msgid="8115290268549503262">"兒童人數"</string>
+ <string name="directory_items" msgid="6645621978998614003">"項目數量"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"遞增"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"遞減"</string>
<string name="drawer_open" msgid="8071673398187261741">"顯示根目錄"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"無法開啟檔案"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"無法開啟封存中的檔案"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"無法刪除部分文件"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"無法載入屬性"</string>
<string name="share_via" msgid="8725082736005677161">"透過以下應用程式分享:"</string>
<string name="copy_notification_title" msgid="52256435625098456">"正在複製檔案"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"正在壓縮檔案"</string>
diff --git a/res/values-zh-rTW/inspector_strings.xml b/res/values-zh-rTW/inspector_strings.xml
new file mode 100644
index 0000000..8c17e39
--- /dev/null
+++ b/res/values-zh-rTW/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"資訊"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"無法載入檔案資訊"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"偵錯資訊 (開發人員專用)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"原始中繼資料:<xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"媒體詳細資料"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"使用以下應用程式開啟這種檔案:"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"這個檔案的提供者:"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"未選取"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"不明"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"尺寸"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g> 百萬像素"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"座標"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>,<xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"高度"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"相機"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"光圈"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"快門速度"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"時間長度"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"拍攝時間"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"焦距"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g> 毫米"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"等效 ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"演出者"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"作曲者"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"專輯"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"位置"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"串流類型"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"原始大小 (位元組)"</string>
+</resources>
diff --git a/res/values-zh-rTW/mimes.xml b/res/values-zh-rTW/mimes.xml
new file mode 100644
index 0000000..cc5cc29
--- /dev/null
+++ b/res/values-zh-rTW/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> 檔案"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"檔案"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"圖片"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> 圖片"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"音訊"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> 音訊"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"影片"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> 影片"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> 封存檔"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Android 應用程式"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"純文字"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"HTML 文件"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"PDF 文件"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Word 文件"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"PowerPoint 簡報"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Excel 試算表"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Google 文件"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Google 試算表"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Google 簡報"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google 繪圖"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Google 表格"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Google 表單"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Google 地圖"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Google 網站"</string>
+ <string name="directory_type" msgid="2702987727566226354">"資料夾"</string>
+</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index bc55dd6..284a5ff 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"壓縮"</string>
<string name="menu_extract" msgid="8171946945982532262">"解壓縮到…"</string>
<string name="menu_rename" msgid="1883113442688817554">"重新命名"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"屬性"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"取得資訊"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"在「<xliff:g id="SOURCE">%1$s</xliff:g>」中查看"</string>
<string name="menu_new_window" msgid="2947837751796109126">"新視窗"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"剪下"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"移動"</string>
<string name="button_dismiss" msgid="7235249361023803349">"關閉"</string>
<string name="button_retry" msgid="4011461781916631389">"再試一次"</string>
+ <string name="button_clear" msgid="5412304437764369441">"清除"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"在供應商的應用程式中顯示"</string>
<string name="not_sorted" msgid="7813496644889115530">"未排序"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"名稱"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"摘要"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"類型"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"大小"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"上次修改時間"</string>
- <string name="directory_children" msgid="8115290268549503262">"兒童人數"</string>
+ <string name="directory_items" msgid="6645621978998614003">"項目數量"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"遞增"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"遞減"</string>
<string name="drawer_open" msgid="8071673398187261741">"顯示根目錄"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"無法開啟檔案"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"無法開啟已封存的檔案"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"無法刪除部分文件"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"無法載入屬性"</string>
<string name="share_via" msgid="8725082736005677161">"分享方式:"</string>
<string name="copy_notification_title" msgid="52256435625098456">"複製檔案"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"正在壓縮檔案"</string>
diff --git a/res/values-zu/inspector_strings.xml b/res/values-zu/inspector_strings.xml
new file mode 100644
index 0000000..3cb972d
--- /dev/null
+++ b/res/values-zu/inspector_strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="inspector_title" msgid="1924760928091740238">"Ulwazi"</string>
+ <string name="inspector_load_error" msgid="7522190243413249291">"Ulwazi lwefayela alikwazanga ukulayishwa"</string>
+ <string name="inspector_debug_section" msgid="2576052661505700421">"Ulwazi lokususa iphutha (i-dev kuphela)"</string>
+ <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Imethadatha e-Raw: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string>
+ <string name="inspector_metadata_section" msgid="6077622515328240575">"Imininingwane yemidiya"</string>
+ <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Lolu hlobo lwefayela luvuleka nge-"</string>
+ <string name="handler_app_belongs_to" msgid="5444507329303253553">"Leli fayela linikezelwe yi-"</string>
+ <string name="handler_app_not_selected" msgid="1294439257183908786">"Abangakhethiwe"</string>
+ <string name="handler_app_unknown" msgid="5911661530593229287">"Akwaziwa"</string>
+ <string name="metadata_dimensions" msgid="6112907724016659801">"Ubukhulu"</string>
+ <string name="metadata_dimensions_format" msgid="6138765871412005962">"<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g> - <xliff:g id="MEGAPIXELS">%3$,.1f</xliff:g>MP"</string>
+ <string name="metadata_coordinates" msgid="6897383227370702734">"Ukuxhumanisa"</string>
+ <string name="metadata_coordinates_format" msgid="1402724596764547761">"<xliff:g id="LATITUDE">%1$,.3f</xliff:g>, <xliff:g id="LONGITUDE">%2$,.3f</xliff:g>"</string>
+ <string name="metadata_altitude" msgid="8063792127436794294">"Ukuphakama"</string>
+ <string name="metadata_camera" msgid="2363009732801281319">"Ikhamera"</string>
+ <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string>
+ <string name="metadata_aperture" msgid="6538741952698935357">"Imbobo"</string>
+ <string name="metadata_shutter_speed" msgid="8204739885103326131">"Isivinini seshutha"</string>
+ <string name="metadata_duration" msgid="3115494422055472715">"Ubude besikhathi"</string>
+ <string name="metadata_date_time" msgid="1090351199248114406">"Ithathwe ngezi"</string>
+ <string name="metadata_focal_length" msgid="3440735161407699893">"Ubude befokhali"</string>
+ <string name="metadata_focal_format" msgid="8542211707962355623">"<xliff:g id="LENGTH">%1$.2f </xliff:g>mm"</string>
+ <string name="metadata_iso_speed_ratings" msgid="1699781252899759058">"Okulinganayo kwe-ISO"</string>
+ <string name="metadata_iso_format" msgid="4153285204012694861">"I-ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string>
+ <string name="metadata_artist" msgid="8972421485694988540">"Umculi"</string>
+ <string name="metadata_composer" msgid="4696926808308256056">"Umqambi"</string>
+ <string name="metadata_album" msgid="1661699531214720236">"I-albhamu"</string>
+ <string name="metadata_address" msgid="1849921023707744640">"Indawo"</string>
+ <string name="debug_stream_types" msgid="2088565280360139333">"Izinhlobo zokusakaza"</string>
+ <string name="debug_raw_size" msgid="7487139640175650185">"Usayizi we-Raw (amabhayithi)"</string>
+</resources>
diff --git a/res/values-zu/mimes.xml b/res/values-zu/mimes.xml
new file mode 100644
index 0000000..b8bf096
--- /dev/null
+++ b/res/values-zu/mimes.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="generic_extention_file_type" msgid="5947398320635880291">"<xliff:g id="EXTENSION">%1$s</xliff:g> ifayela"</string>
+ <string name="generic_file_type" msgid="1415477154743494280">"Ifayela"</string>
+ <string name="image_file_type" msgid="3011633523704887793">"Isithombe"</string>
+ <string name="image_extension_file_type" msgid="992617216367594851">"<xliff:g id="FILETYPE">%1$s</xliff:g> isithombe"</string>
+ <string name="audio_file_type" msgid="3790525543519624632">"Umsindo"</string>
+ <string name="audio_extension_file_type" msgid="6334293531796491314">"<xliff:g id="FILETYPE">%1$s</xliff:g> umsindo"</string>
+ <string name="video_file_type" msgid="7290473366042482095">"Ividiyo"</string>
+ <string name="video_extension_file_type" msgid="6352763029831291433">"<xliff:g id="FILETYPE">%1$s</xliff:g> ividiyo"</string>
+ <string name="archive_file_type" msgid="1463432996680398798">"<xliff:g id="FILETYPE">%1$s</xliff:g> ingobo yomlando"</string>
+ <string name="apk_file_type" msgid="6004275470389462277">"Uhlelo lokusebenza lwe-Android"</string>
+ <string name="txt_file_type" msgid="4677767777860724696">"Umbhalo ongenalutho"</string>
+ <string name="html_file_type" msgid="2034229603117527970">"Idokhumenti ye-HTML"</string>
+ <string name="pdf_file_type" msgid="3382260303795039988">"Idokhumenti ye-PDF"</string>
+ <string name="word_file_type" msgid="2366349268129894972">"Idokhumenti ye-Word"</string>
+ <string name="ppt_file_type" msgid="2570841599899893925">"Iphrezentheshini ye-PowerPoint"</string>
+ <string name="excel_file_type" msgid="8363932635044575463">"Isipredishithi se-Excel"</string>
+ <string name="gdoc_file_type" msgid="242328101061228382">"Idokhumenti ye-Google"</string>
+ <string name="gsheet_file_type" msgid="8055591929133067952">"Isipredishithi se-Google"</string>
+ <string name="gslides_file_type" msgid="8359750985956690177">"Iphrezentheshini ye-Google"</string>
+ <string name="gdraw_file_type" msgid="655688091676820371">"Google imidwebo"</string>
+ <string name="gtable_file_type" msgid="7332773878374650335">"Ithebula ye-Google"</string>
+ <string name="gform_file_type" msgid="4803176103746107611">"Ifomu le-Google"</string>
+ <string name="gmap_file_type" msgid="6684180781808007016">"Imephu ye-Google"</string>
+ <string name="gsite_file_type" msgid="3742812051249149526">"Isayithi le-Google"</string>
+ <string name="directory_type" msgid="2702987727566226354">"Ifolda"</string>
+</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 1d80f8b..3109dc0 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -41,7 +41,7 @@
<string name="menu_compress" msgid="37539111904724188">"Cindezela"</string>
<string name="menu_extract" msgid="8171946945982532262">"Khiphela ku…"</string>
<string name="menu_rename" msgid="1883113442688817554">"Qamba kabusha"</string>
- <string name="menu_inspector" msgid="8633147986551632467">"Izici"</string>
+ <string name="menu_inspect" msgid="7279855349299446224">"Thola ulwazi"</string>
<string name="menu_view_in_owner" msgid="7228948660557554770">"Buka ku-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="menu_new_window" msgid="2947837751796109126">"Iwindi elisha"</string>
<string name="menu_cut_to_clipboard" msgid="2878752142015026229">"Sika"</string>
@@ -57,13 +57,15 @@
<string name="button_move" msgid="8596460499325291272">"Hambisa"</string>
<string name="button_dismiss" msgid="7235249361023803349">"Cashisa"</string>
<string name="button_retry" msgid="4011461781916631389">"Zama Futhi"</string>
+ <string name="button_clear" msgid="5412304437764369441">"Sula"</string>
+ <string name="button_show_provider" msgid="6905880493806292753">"Bonisa kumhlinzeki"</string>
<string name="not_sorted" msgid="7813496644889115530">"Akuhlungiwe"</string>
<string name="sort_dimension_name" msgid="6325591541414177579">"Igama"</string>
<string name="sort_dimension_summary" msgid="7724534446881397860">"Isifinyezo"</string>
<string name="sort_dimension_file_type" msgid="5779709622922085381">"Uhlobo"</string>
<string name="sort_dimension_size" msgid="2190547351159472884">"Usayizi"</string>
<string name="sort_dimension_date" msgid="4231005651895254033">"Kulungisiwe"</string>
- <string name="directory_children" msgid="8115290268549503262">"Inombolo yezingane"</string>
+ <string name="directory_items" msgid="6645621978998614003">"Inombolo yezinto"</string>
<string name="sort_direction_ascending" msgid="5882787683763248102">"Iyanyuka"</string>
<string name="sort_direction_descending" msgid="1729187589765894076">"Iyehla"</string>
<string name="drawer_open" msgid="8071673398187261741">"Bonisa izimpande"</string>
@@ -82,7 +84,6 @@
<string name="toast_no_application" msgid="7555319548595113121">"Ayikwazanga ukuvula ifayela"</string>
<string name="toast_view_in_archives_unsupported" msgid="1923221390170964845">"Ayikwazi ukuvula amafayela kuzingobo zomlando"</string>
<string name="toast_failed_delete" msgid="3453846588205817591">"Ayikwazi ukususa amanye amadokhumenti"</string>
- <string name="file_inspector_load_error" msgid="1226344446677541109">"Izakhiwo azikwazanga ukulayishwa"</string>
<string name="share_via" msgid="8725082736005677161">"Abelana nge-"</string>
<string name="copy_notification_title" msgid="52256435625098456">"Ikopisha amafayela"</string>
<string name="compress_notification_title" msgid="6830195148113751021">"Icindezela amafayela"</string>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index e7801b9..818e012 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -76,5 +76,8 @@
<color name="scroll_track">#fff0f0f0</color>
<color name="inspector_value">#ff939393</color>
+ <color name="inspector_link">#6633b5e5</color>
<color name="inspector_section_title">#ff939393</color>
+ <color name="inspector_section_divider">#E0E0E0</color>
+ <color name="inspector_title_background">#40000000</color>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 978cc5f..763cfc0 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -48,7 +48,7 @@
<bool name="feature_remote_actions">true</bool>
<bool name="feature_system_keyboard_navigation">true</bool>
<bool name="feature_virtual_files_sharing">true</bool>
- <bool name="feature_inspector">false</bool>
+ <bool name="feature_inspector">true</bool>
<bool name="feature_debug_mode">false</bool>
<!-- Indicates if internal storage is shown as default or not. -->
diff --git a/res/values/inspector_strings.xml b/res/values/inspector_strings.xml
new file mode 100644
index 0000000..a70a274
--- /dev/null
+++ b/res/values/inspector_strings.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- File properties dialog title. This dialog show fine grained details about a file. -->
+ <string name="inspector_title">Info</string>
+
+ <!-- File properties dialog error shown when information about a file could not be loaded-->
+ <string name="inspector_load_error">File info could not be loaded</string>
+
+ <!-- Title of inspector's debug information section. The contents of this section
+ features detailed "internal" information useful primarily to developers.
+ This section is only visible to developers or people running debug builds. [CHAR LIMIT=48] -->
+ <string name="inspector_debug_section">Debug info (dev only)</string>
+
+ <!-- Title of inspector's debug info metadata sub-section. [CHAR LIMIT=48] -->
+ <string name="inspector_debug_metadata_section">Raw metadata: <xliff:g id="metadataType" example="EXIF">%1$s</xliff:g></string>
+
+ <!-- Title of inspector's media details info section. Shows information related to camera, dimensions, and authors. -->
+ <string name="inspector_metadata_section">Media details</string>
+
+ <!-- File properties dialog section title. In this section we show information about the default handler application for this type of file.-->
+ <string name="handler_app_file_opens_with">This kind of file opens with</string>
+ <!-- File properties dialog section title. In this section we show information about the applicaiton that provides the file.
+ Examples of such applicaitons are: Box, Microsoft OneDrive, and Google Drive, etc)-->
+ <string name="handler_app_belongs_to">This file is supplied by</string>
+
+ <!-- File properties dialog user message if a default app has not been selected-->
+ <string name="handler_app_not_selected">Not selected</string>
+ <!-- File properties dialog user message if the default app is unknown-->
+ <string name="handler_app_unknown">Unknown</string>
+
+ <!-- The height and width of a photo. -->
+ <string name="metadata_dimensions">Dimensions</string>
+ <!-- The width and height of a photo, followed by a the "megapixel rating".
+ Cameras are frequently rated by "megapixels". In U.S. English the "megapixels" rating
+ of a camera is denoted by a number followed by "MP". E.g. 12.2MP or 8MP. -->
+ <string name="metadata_dimensions_format"><xliff:g id="width" example="1280">%1$d</xliff:g> x <xliff:g id="height" example="1024">%2$d</xliff:g> - <xliff:g id="megapixels" example="12.2">%3$,.1f</xliff:g>MP</string>
+ <!-- The location of where a photo was taken. -->
+ <string name="metadata_coordinates">Coordinates</string>
+ <!-- The location a photo was taken in the form of latitude/longitude coordinates. -->
+ <string name="metadata_coordinates_format"><xliff:g id="latitude" example="33.996">%1$,.3f</xliff:g>, <xliff:g id="longitude" example="-118.476">%2$,.3f</xliff:g></string>
+ <!-- The elevation a photo was taken. -->
+ <string name="metadata_altitude">Altitude</string>
+ <!-- The camera make and model. -->
+ <string name="metadata_camera">Camera</string>
+ <!-- The camera make and model. Where make is usually the company, and model is the individual camera model name. -->
+ <string name="metadata_camera_format"><xliff:g id="make" example="Sony">%1$s</xliff:g> <xliff:g id="model" example="Snazzy Snapper">%2$s</xliff:g></string>
+ <!-- The value of a photos aperture. Note that this is probably camera EXIF data.-->
+ <string name="metadata_aperture">Aperture</string>
+ <!-- The value of a photos shutter speed. Note that this is probably camera EXIF data.-->
+ <string name="metadata_shutter_speed">Shutter speed</string>
+ <!-- How long a video/audio file is.-->
+ <string name="metadata_duration">Duration</string>
+ <!-- When a photo was taken. Note that this is probably camera EXIF data.-->
+ <string name="metadata_date_time">Taken on</string>
+ <!-- Message presenting EXIF aperture information in the tradition "f/2.0" format familiar to users. This format is basically an industry standard that shouldn't be translated, so it is marked as not translatable. -->
+ <string name="metadata_aperture_format" translatable="false">f/<xliff:g id="aperture" example="2.0">%1$,.1f</xliff:g></string>
+ <!--The tag for the focal length of a camera. Note that this is probably camera EXIF data-->
+ <string name="metadata_focal_length">Focal length</string>
+ <!--The format for displaying the focal length of a camera. Note that this is probably camera EXIF data-->
+ <string name="metadata_focal_format"><xliff:g id="length" example="24">%1$.2f </xliff:g>mm</string>
+ <!--The tag for the ISO Speed of a camera. Note that this is probably camera EXIF data-->
+ <string name="metadata_iso_speed_ratings">ISO equivalent</string>
+ <!--The format for displaying ISO speed. Note that this is probably camera EXIF data-->
+ <string name="metadata_iso_format">ISO <xliff:g id="iso_speed" example="35">%1$d</xliff:g></string>
+ <!--The title of the audio file, Note this is probably MP3 ID3 tags.-->
+ <string name="metadata_artist">Artist</string>
+ <!--The composer for the audio file, Note this is probably MP3 ID3 tags-->
+ <string name="metadata_composer">Composer</string>
+ <!--The title of the album (i.e. collection of recordings) the song belongs to. Note this is probably MP3 ID3 tags-->
+ <string name="metadata_album">Album</string>
+ <!-- The address nearest to where a photo was taken -->
+ <string name="metadata_address">Location</string>
+
+ <!-- String label for developer/debug file details, specifying which stream types are available. -->
+ <string name="debug_stream_types">Stream types</string>
+ <!-- String label for developer/debug file details, specifying the size of the file in bytes. -->
+ <string name="debug_raw_size">Raw size (bytes)</string>
+ <!-- String label for developer/debug file details, specifying a file's uri/content address. -->
+ <string name="debug_content_uri" translatable="false">Uri</string>
+ <!-- String label for developer/debug file details, specifying document id. -->
+ <string name="debug_document_id" translatable="false">Document id</string>
+ <!-- String label for developer/debug file details, specifying mimetype. -->
+ <string name="debug_raw_mimetype" translatable="false">Raw mimetype</string>
+ <!-- String label for developer/debug file details, specifying that a file is an archive. -->
+ <string name="debug_is_archive" translatable="false">Is archive</string>
+ <!-- String label for developer/debug file details, specifying that a file is a container (like a folder or an archive). -->
+ <string name="debug_is_container" translatable="false">Is container</string>
+ <!-- String label for developer/debug file details, specifying that a file is partial (being downloaded). -->
+ <string name="debug_is_partial" translatable="false">Is partial</string>
+ <!-- String label for developer/debug file details, specifying that a file is virtual (has no byte representation). -->
+ <string name="debug_is_virtual" translatable="false">Is virtual</string>
+ <!-- String label for developer/debug file details, specifying that a file supports creating files within it. -->
+ <string name="debug_supports_create" translatable="false">Supports create</string>
+ <!-- String label for developer/debug file details, specifying that a file is deletable. -->
+ <string name="debug_supports_delete" translatable="false">Supports delete</string>
+ <!-- String label for developer/debug file details, specifying that a file has associated metadata. -->
+ <string name="debug_supports_metadata" translatable="false">Supports metadata</string>
+ <!-- String label for developer/debug file details, specifying that a file can be removed. -->
+ <string name="debug_supports_remove" translatable="false">Supports remove</string>
+ <!-- String label for developer/debug file details, specifying that a file can be renamed. -->
+ <string name="debug_supports_rename" translatable="false">Supports rename</string>
+ <!-- String label for developer/debug file details, specifying that a file supports the "settings" feature. -->
+ <string name="debug_supports_settings" translatable="false">Supports settings</string>
+ <!-- String label for developer/debug file details, specifying that a file has a viewable thumbnail. -->
+ <string name="debug_supports_thumbnail" translatable="false">Supports thumbnail</string>
+ <!-- String label for developer/debug file details, specifying that a file supports the "weblink" feature. -->
+ <string name="debug_supports_weblink" translatable="false">Supports weblink</string>
+ <!-- String label for developer/debug file details, specifying that a file is writable. -->
+ <string name="debug_supports_write" translatable="false">Supports write</string>
+
+</resources>
diff --git a/res/values/mimes.xml b/res/values/mimes.xml
index 6823ed9..0559741 100644
--- a/res/values/mimes.xml
+++ b/res/values/mimes.xml
@@ -16,54 +16,54 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Generic file type with an extention shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Generic file type with an extention shown in type column in list view. [CHAR LIMIT=30] -->
<string name="generic_extention_file_type"><xliff:g id="extension" example="APE">%1$s</xliff:g> file</string>
- <!-- Generic file type without an extention shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Generic file type without an extention shown in type column in list view. [CHAR LIMIT=30] -->
<string name="generic_file_type">File</string>
- <!-- Generic image file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Generic image file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="image_file_type">Image</string>
- <!-- Image file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Image file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="image_extension_file_type"><xliff:g id="fileType" example="JPG">%1$s</xliff:g> image</string>
- <!-- Generic audio file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Generic audio file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="audio_file_type">Audio</string>
- <!-- Audio file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Audio file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="audio_extension_file_type"><xliff:g id="fileType" example="MP3">%1$s</xliff:g> audio</string>
- <!-- Generic video file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Generic video file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="video_file_type">Video</string>
- <!-- Video file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Video file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="video_extension_file_type"><xliff:g id="fileType" example="AVI">%1$s</xliff:g> video</string>
- <!-- Archive file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Archive file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="archive_file_type"><xliff:g id="fileType" example="Zip">%1$s</xliff:g> archive</string>
- <!-- Android application file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Android application file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="apk_file_type">Android application</string>
- <!-- Plain text file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Plain text file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="txt_file_type">Plain text</string>
- <!-- HTML file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- HTML file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="html_file_type">HTML document</string>
- <!-- PDF file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- PDF file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="pdf_file_type">PDF document</string>
- <!-- Word document file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Word document file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="word_file_type">Word document</string>
- <!-- PowerPoint presentation file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- PowerPoint presentation file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="ppt_file_type">PowerPoint presentation</string>
- <!-- Excel spreadsheet file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Excel spreadsheet file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="excel_file_type">Excel spreadsheet</string>
- <!-- Google document file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google document file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gdoc_file_type">Google document</string>
- <!-- Google spreadsheet file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google spreadsheet file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gsheet_file_type">Google spreadsheet</string>
- <!-- Google presentation file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google presentation file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gslides_file_type">Google presentation</string>
- <!-- Google drawing file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google drawing file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gdraw_file_type">Google drawing</string>
- <!-- Google table file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google table file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gtable_file_type">Google table</string>
- <!-- Google form file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google form file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gform_file_type">Google form</string>
- <!-- Google map file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google map file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gmap_file_type">Google map</string>
- <!-- Google site file type shown in type column in list view. [CHAR LIMIT=24] -->
+ <!-- Google site file type shown in type column in list view. [CHAR LIMIT=30] -->
<string name="gsite_file_type">Google site</string>
<!-- Generic directory type shown when viewing a folder in the properties view -->
<string name="directory_type">Folder</string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a5ecfac..2855ef5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -18,7 +18,7 @@
<!-- Title of the Files application [CHAR LIMIT=32] -->
<string name="files_label">Files</string>
- <!-- Title of the Downloads application, which sometimes Files is known as [CHAR LIMIT=32] -->
+ <!-- Title of the Downloads application, which sometimes Files is known as [CHAR LIMIT=16] -->
<string name="downloads_label">Downloads</string>
<!-- Title of the documents application [CHAR LIMIT=32] -->
@@ -67,8 +67,8 @@
<string name="menu_extract">Extract to\u2026</string>
<!-- Menu item that renames the selected document [CHAR LIMIT=28] -->
<string name="menu_rename">Rename</string>
- <!--Menu item that displays properties about the selected document [CHAR LIMIT=28] -->
- <string name="menu_inspector">Get info</string>
+ <!-- Menu item that displays properties about the selected document [CHAR LIMIT=28] -->
+ <string name="menu_inspect">Get info</string>
<!-- Menu item that renames the selected document [CHAR LIMIT=28] -->
<string name="menu_view_in_owner">View in <xliff:g id="source" example="Google Drive">%1$s</xliff:g></string>
@@ -103,6 +103,11 @@
<!-- Button label that hides the error bar [CHAR LIMIT=24] -->
<string name="button_dismiss">Dismiss</string>
<string name="button_retry">Try Again</string>
+ <!-- Button label that removes the default application to open a file. -->
+ <string name="button_clear">Clear</string>
+ <!-- Button label that show in the providers service. Many providers have their own app such
+ as google drive. Pressing this button would open in the file in the providers app. -->
+ <string name="button_show_provider">Show in provider</string>
<!-- A string used to show user that currently documents are not sorted in any given order. [CHAR_LIMIT=30] -->
<string name="not_sorted">Not sorted</string>
@@ -120,26 +125,6 @@
<!--Table header for number of items in a folder.-->
<string name="directory_items">Number of items</string>
- <!--File properties dialog section title. In this section we show information about the default handler application for this type of file.-->
- <string name="handler_app_file_opens_with">This kind of file opens with</string>
- <!--File properties dialog section title. In this section we show information about a files provider. (e.g. system, drive, dropbox, etc)-->
- <string name="handler_app_belongs_to">This file belongs to</string>
-
- <!--File properties dialog button description for clearing the default app. the name of the app
- will be inserted programmatically inbetween these two strings-->
- <string name="handler_app_button_info_1">Other apps can open this file type. Clear</string>
- <string name="handler_app_button_info_2">as the default.</string>
-
- <!--File properties dialog button label to clear the default app-->
- <string name="handler_app_clear">Clear</string>
- <!--File properties dialog button label to show a document in a provider-->
- <string name="handler_app_show_in">Show in provider</string>
-
- <!--File properties dialog user message if a default app has not been selected-->
- <string name="handler_app_not_selected">Not selected</string>
- <!--File properties dialog user message if the default app is unknown-->
- <string name="handler_app_unknown">Unknown</string>
-
<!-- content description to describe ascending sorting used with upward arrow in table header. -->
<string name="sort_direction_ascending">Ascending</string>
<!-- content description to describe descending sorting used with downward arrow in table header. -->
@@ -183,9 +168,6 @@
<!-- Toast shown when some of the selected documents failed to be deleted [CHAR LIMIT=48] -->
<string name="toast_failed_delete">Unable to delete some documents</string>
- <!-- Toast shown when a files document info fails to load-->
- <string name="file_inspector_load_error">Properties could not be loaded</string>
-
<!-- Title of dialog when prompting user to select an app to share documents with [CHAR LIMIT=32] -->
<string name="share_via">Share via</string>
@@ -386,8 +368,4 @@
<!-- Button for continuing a file operation in background, eg. copying, moving or extracting. [CHAR LIMIT=48] -->
<string name="continue_in_background">Continue in background</string>
-
- <!-- Title of inspector's debug info section. [CHAR LIMIT=48] -->
- <string name="inspector_debug_section">Debug info (dev only)</string>
-
</resources>
diff --git a/src/com/android/documentsui/AbstractActionHandler.java b/src/com/android/documentsui/AbstractActionHandler.java
index 0faab6e..44c6342 100644
--- a/src/com/android/documentsui/AbstractActionHandler.java
+++ b/src/com/android/documentsui/AbstractActionHandler.java
@@ -51,15 +51,16 @@
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.AnimationView;
import com.android.documentsui.dirlist.AnimationView.AnimationType;
-import com.android.documentsui.dirlist.DocumentDetails;
import com.android.documentsui.dirlist.FocusHandler;
import com.android.documentsui.files.LauncherActivity;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.roots.GetRootDocumentTask;
import com.android.documentsui.roots.LoadRootTask;
import com.android.documentsui.roots.ProvidersAccess;
-import com.android.documentsui.selection.Selection;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.ContentLock;
+import com.android.documentsui.selection.MutableSelection;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
import com.android.documentsui.sidebar.EjectRootTask;
import com.android.documentsui.ui.Snackbars;
@@ -92,7 +93,7 @@
protected final ProvidersAccess mProviders;
protected final DocumentsAccess mDocs;
protected final FocusHandler mFocusHandler;
- protected final SelectionManager mSelectionMgr;
+ protected final SelectionHelper mSelectionMgr;
protected final SearchViewManager mSearchMgr;
protected final Lookup<String, Executor> mExecutors;
protected final Injector<?> mInjector;
@@ -101,7 +102,7 @@
private Runnable mDisplayStateChangedListener;
- private DirectoryReloadLock mDirectoryReloadLock;
+ private ContentLock mContentLock;
@Override
public void registerDisplayStateChangedListener(Runnable l) {
@@ -226,10 +227,11 @@
}
@Override
- public boolean openDocument(DocumentDetails doc, @ViewType int type, @ViewType int fallback) {
+ public boolean openItem(ItemDetails doc, @ViewType int type, @ViewType int fallback) {
throw new UnsupportedOperationException("Can't open document.");
}
+ @Override
public void showInspector(DocumentInfo doc) {
throw new UnsupportedOperationException("Can't open properties.");
}
@@ -356,6 +358,13 @@
+ mState.stack.getRoot());
}
+ final DocumentInfo top = stack.peek();
+ if (top.isArchive()) {
+ // Swap the zip file in original provider and the one provided by ArchiveProvider.
+ stack.pop();
+ stack.push(mDocs.getArchiveDocument(top.derivedUri));
+ }
+
mState.stack.reset();
// Update navigator to give horizontal breadcrumb a chance to update documents. It
// doesn't update its content if the size of document stack doesn't change.
@@ -524,13 +533,15 @@
loadRoot(Shared.getDefaultRootUri(mActivity));
}
- protected Selection getStableSelection() {
- return mSelectionMgr.getSelection(new Selection());
+ protected MutableSelection getStableSelection() {
+ MutableSelection selection = new MutableSelection();
+ mSelectionMgr.copySelection(selection);
+ return selection;
}
@Override
- public ActionHandler reset(DirectoryReloadLock reloadLock) {
- mDirectoryReloadLock = reloadLock;
+ public ActionHandler reset(ContentLock reloadLock) {
+ mContentLock = reloadLock;
mActivity.getLoaderManager().destroyLoader(LOADER_ID);
return this;
}
@@ -578,7 +589,7 @@
contentsUri,
mState.sortModel,
mInjector.fileTypeLookup,
- mDirectoryReloadLock,
+ mContentLock,
mSearchMgr.isSearching());
}
}
diff --git a/src/com/android/documentsui/ActionHandler.java b/src/com/android/documentsui/ActionHandler.java
index 6b0e077..ba20f34 100644
--- a/src/com/android/documentsui/ActionHandler.java
+++ b/src/com/android/documentsui/ActionHandler.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.app.PendingIntent;
import android.content.ContentProvider;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
@@ -29,8 +28,8 @@
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.RootInfo;
-import com.android.documentsui.dirlist.DocumentDetails;
-import com.android.documentsui.selection.Selection;
+import com.android.documentsui.selection.ContentLock;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -111,7 +110,7 @@
* If container, then opens the container, otherwise views using the specified type of view.
* If the primary view type is unavailable, then fallback to the alternative type of view.
*/
- boolean openDocument(DocumentDetails doc, @ViewType int type, @ViewType int fallback);
+ boolean openItem(ItemDetails doc, @ViewType int type, @ViewType int fallback);
/**
* This is called when user hovers over a doc for enough time during a drag n' drop, to open a
@@ -158,5 +157,5 @@
* Allow action handler to be initialized in a new scope.
* @return this
*/
- <T extends ActionHandler> T reset(DirectoryReloadLock reloadLock);
+ <T extends ActionHandler> T reset(ContentLock contentLock);
}
diff --git a/src/com/android/documentsui/ActionModeController.java b/src/com/android/documentsui/ActionModeController.java
index 7c5ad63..aabd672 100644
--- a/src/com/android/documentsui/ActionModeController.java
+++ b/src/com/android/documentsui/ActionModeController.java
@@ -24,7 +24,6 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.ActionMode;
-import android.view.HapticFeedbackConstants;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -35,22 +34,20 @@
import com.android.documentsui.base.EventHandler;
import com.android.documentsui.base.Menus;
import com.android.documentsui.selection.Selection;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.SelectionHelper.SelectionObserver;
import com.android.documentsui.ui.MessageBuilder;
-import java.util.function.Consumer;
-import java.util.function.IntConsumer;
-
/**
* A controller that listens to selection changes and manages life cycles of action modes.
*/
-public class ActionModeController
- implements SelectionManager.Callback, ActionMode.Callback, ActionModeAddons {
+public class ActionModeController extends SelectionObserver
+ implements ActionMode.Callback, ActionModeAddons {
private static final String TAG = "ActionModeController";
private final Activity mActivity;
- private final SelectionManager mSelectionMgr;
+ private final SelectionHelper mSelectionMgr;
private final MenuManager mMenuManager;
private final MessageBuilder mMessages;
@@ -62,7 +59,7 @@
public ActionModeController(
Activity activity,
- SelectionManager selectionMgr,
+ SelectionHelper selectionMgr,
MenuManager menuManager,
MessageBuilder messages) {
@@ -74,7 +71,7 @@
@Override
public void onSelectionChanged() {
- mSelectionMgr.getSelection(mSelected);
+ mSelectionMgr.copySelection(mSelected);
if (mSelected.size() > 0) {
if (mActionMode == null) {
if (DEBUG) Log.d(TAG, "Starting action mode.");
@@ -99,27 +96,7 @@
@Override
public void onSelectionRestored() {
- mSelectionMgr.getSelection(mSelected);
- if (mSelected.size() > 0) {
- if (mActionMode == null) {
- if (DEBUG) Log.d(TAG, "Starting action mode.");
- mActionMode = mActivity.startActionMode(this);
- }
- updateActionMenu();
- } else {
- if (mActionMode != null) {
- if (DEBUG) Log.d(TAG, "Finishing action mode.");
- mActionMode.finish();
- }
- }
-
- if (mActionMode != null) {
- assert(!mSelected.isEmpty());
- final String title = mMessages.getQuantityString(
- R.plurals.elements_selected, mSelected.size());
- mActionMode.setTitle(title);
- mActivity.getWindow().setTitle(title);
- }
+ onSelectionChanged();
}
// Called when the user exits the action mode
@@ -135,9 +112,7 @@
mActionMode = null;
mMenu = null;
- // clear selection
mSelectionMgr.clearSelection();
- mSelected.clear();
// Reset window title back to activity title, i.e. Root name
mActivity.getWindow().setTitle(mActivity.getTitle());
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index 290dd63..19457fc 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -425,12 +425,10 @@
}
mNavigator.update();
+
// Causes talkback to announce the activity's new title
- if (mState.stack.isRecents()) {
- setTitle(mProviders.getRecentsRoot().title);
- } else {
- setTitle(mState.stack.getTitle());
- }
+ setTitle(mState.stack.getTitle());
+
invalidateOptionsMenu();
}
diff --git a/src/com/android/documentsui/DirectoryLoader.java b/src/com/android/documentsui/DirectoryLoader.java
index 30a447c..64d97f0 100644
--- a/src/com/android/documentsui/DirectoryLoader.java
+++ b/src/com/android/documentsui/DirectoryLoader.java
@@ -43,6 +43,7 @@
import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.roots.RootCursorWrapper;
+import com.android.documentsui.selection.ContentLock;
import com.android.documentsui.sorting.SortModel;
import libcore.io.IoUtils;
@@ -74,7 +75,7 @@
Uri uri,
SortModel model,
Lookup<String, String> fileTypeLookup,
- DirectoryReloadLock lock,
+ ContentLock lock,
boolean inSearchMode) {
super(context, ProviderExecutor.forAuthority(root.authority));
@@ -226,10 +227,10 @@
}
private static final class LockingContentObserver extends ContentObserver {
- private final DirectoryReloadLock mLock;
+ private final ContentLock mLock;
private final Runnable mContentChangedCallback;
- public LockingContentObserver(DirectoryReloadLock lock, Runnable contentChangedCallback) {
+ public LockingContentObserver(ContentLock lock, Runnable contentChangedCallback) {
super(new Handler(Looper.getMainLooper()));
mLock = lock;
mContentChangedCallback = contentChangedCallback;
@@ -242,7 +243,7 @@
@Override
public void onChange(boolean selfChange) {
- mLock.tryUpdate(mContentChangedCallback);
+ mLock.runWhenUnlocked(mContentChangedCallback);
}
}
}
diff --git a/src/com/android/documentsui/DirectoryReloadLock.java b/src/com/android/documentsui/DirectoryReloadLock.java
deleted file mode 100644
index 4299914..0000000
--- a/src/com/android/documentsui/DirectoryReloadLock.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import static com.android.documentsui.base.Shared.VERBOSE;
-
-import android.annotation.MainThread;
-import android.annotation.Nullable;
-import android.util.Log;
-
-import com.android.documentsui.base.Shared;
-import com.android.documentsui.selection.BandController;
-
-/**
- * A lock used by {@link DirectoryLoader} and {@link BandController} to ensure refresh is blocked
- * while Band Selection is active.
- */
-public final class DirectoryReloadLock {
- private static final String TAG = "DirectoryReloadLock";
-
- private int mPauseCount = 0;
- private @Nullable Runnable mCallback;
-
- /**
- * Increment the block count by 1
- */
- @MainThread
- public void block() {
- Shared.checkMainLoop();
- mPauseCount++;
- if (VERBOSE) Log.v(TAG, "Block count increments to " + mPauseCount + ".");
- }
-
- /**
- * Decrement the block count by 1; If no other object is trying to block and there exists some
- * callback, that callback will be run
- */
- @MainThread
- public void unblock() {
- Shared.checkMainLoop();
- assert(mPauseCount > 0);
- mPauseCount--;
- if (VERBOSE) Log.v(TAG, "Block count decrements to " + mPauseCount + ".");
- if (mPauseCount == 0 && mCallback != null) {
- mCallback.run();
- mCallback = null;
- }
- }
-
- /**
- * Attempts to run the given Runnable if not-blocked, or else the Runnable is set to be ran next
- * (replacing any previous set Runnables).
- */
- public void tryUpdate(Runnable update) {
- if (mPauseCount == 0) {
- update.run();
- } else {
- mCallback = update;
- }
- }
-}
diff --git a/src/com/android/documentsui/DocsSelectionHelper.java b/src/com/android/documentsui/DocsSelectionHelper.java
new file mode 100644
index 0000000..2c6b63b
--- /dev/null
+++ b/src/com/android/documentsui/DocsSelectionHelper.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.RecyclerView;
+
+import com.android.documentsui.selection.DefaultSelectionHelper;
+import com.android.documentsui.selection.DefaultSelectionHelper.SelectionMode;
+import com.android.documentsui.selection.Selection;
+import com.android.documentsui.selection.SelectionHelper;
+
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+/**
+ * DocumentsUI SelectManager implementation that creates delegate instances
+ * each time reset is called.
+ */
+public final class DocsSelectionHelper extends SelectionHelper {
+
+ private final DelegateFactory mFactory;
+ private final @SelectionMode int mSelectionMode;
+
+ private @Nullable SelectionHelper mDelegate;
+
+ @VisibleForTesting
+ DocsSelectionHelper(DelegateFactory factory, @SelectionMode int mode) {
+ mFactory = factory;
+ mSelectionMode = mode;
+ }
+
+ public SelectionHelper reset(
+ RecyclerView.Adapter<?> adapter,
+ StableIdProvider stableIds,
+ SelectionPredicate canSetState) {
+
+ if (mDelegate != null) {
+ mDelegate.clearSelection();
+ }
+
+ mDelegate = mFactory.create(mSelectionMode, adapter, stableIds, canSetState);
+ return this;
+ }
+
+ @Override
+ public void addObserver(SelectionObserver listener) {
+ mDelegate.addObserver(listener);
+ }
+
+ @Override
+ public boolean hasSelection() {
+ return mDelegate.hasSelection();
+ }
+
+ @Override
+ public Selection getSelection() {
+ return mDelegate.getSelection();
+ }
+
+ @Override
+ public void copySelection(Selection dest) {
+ mDelegate.copySelection(dest);
+ }
+
+ @Override
+ public boolean isSelected(String id) {
+ return mDelegate.isSelected(id);
+ }
+
+ @VisibleForTesting
+ public void replaceSelection(Iterable<String> ids) {
+ mDelegate.clearSelection();
+ mDelegate.setItemsSelected(ids, true);
+ }
+
+ @Override
+ public void restoreSelection(Selection other) {
+ mDelegate.restoreSelection(other);
+ }
+
+ @Override
+ public boolean setItemsSelected(Iterable<String> ids, boolean selected) {
+ return mDelegate.setItemsSelected(ids, selected);
+ }
+
+ @Override
+ public void clearSelection() {
+ mDelegate.clearSelection();
+ }
+
+ @Override
+ public boolean select(String modelId) {
+ return mDelegate.select(modelId);
+ }
+
+ @Override
+ public boolean deselect(String modelId) {
+ return mDelegate.deselect(modelId);
+ }
+
+ @Override
+ public void startRange(int pos) {
+ mDelegate.startRange(pos);
+ }
+
+ @Override
+ public void extendRange(int pos) {
+ mDelegate.extendRange(pos);
+ }
+
+ @Override
+ public void extendProvisionalRange(int pos) {
+ mDelegate.extendProvisionalRange(pos);
+ }
+
+ @Override
+ public void clearProvisionalSelection() {
+ mDelegate.clearProvisionalSelection();
+ }
+
+ @Override
+ public void setProvisionalSelection(Set<String> newSelection) {
+ mDelegate.setProvisionalSelection(newSelection);
+ }
+
+ @Override
+ public void mergeProvisionalSelection() {
+ mDelegate.mergeProvisionalSelection();
+ }
+
+ @Override
+ public void endRange() {
+ mDelegate.endRange();
+ }
+
+ @Override
+ public boolean isRangeActive() {
+ return mDelegate.isRangeActive();
+ }
+
+ @Override
+ public void anchorRange(int position) {
+ mDelegate.anchorRange(position);
+ }
+
+ public static DocsSelectionHelper createMultiSelect() {
+ return new DocsSelectionHelper(
+ DelegateFactory.INSTANCE,
+ DefaultSelectionHelper.MODE_MULTIPLE);
+ }
+
+ public static DocsSelectionHelper createSingleSelect() {
+ return new DocsSelectionHelper(
+ DelegateFactory.INSTANCE,
+ DefaultSelectionHelper.MODE_SINGLE);
+ }
+
+ /**
+ * Use of a factory to create selection manager instances allows testable instances to
+ * be inject from tests.
+ */
+ @VisibleForTesting
+ static class DelegateFactory {
+ static final DelegateFactory INSTANCE = new DelegateFactory();
+
+ SelectionHelper create(
+ @SelectionMode int mode,
+ RecyclerView.Adapter<?> adapter,
+ StableIdProvider stableIds,
+ SelectionPredicate canSetState) {
+
+ return new DefaultSelectionHelper(mode, adapter, stableIds, canSetState);
+ }
+ }
+}
diff --git a/src/com/android/documentsui/FocusManager.java b/src/com/android/documentsui/FocusManager.java
index 609d127..097516e 100644
--- a/src/com/android/documentsui/FocusManager.java
+++ b/src/com/android/documentsui/FocusManager.java
@@ -47,8 +47,8 @@
import com.android.documentsui.dirlist.DocumentHolder;
import com.android.documentsui.dirlist.DocumentsAdapter;
import com.android.documentsui.dirlist.FocusHandler;
+import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.Model.Update;
-import com.android.documentsui.selection.SelectionManager;
import java.util.ArrayList;
import java.util.List;
@@ -61,7 +61,7 @@
private final ContentScope mScope = new ContentScope();
private final Features mFeatures;
- private final SelectionManager mSelectionMgr;
+ private final SelectionHelper mSelectionMgr;
private final DrawerController mDrawer;
private final Procedure mRootsFocuser;
private final TitleSearchHelper mSearchHelper;
@@ -70,7 +70,7 @@
public FocusManager(
Features features,
- SelectionManager selectionMgr,
+ SelectionHelper selectionMgr,
DrawerController drawer,
Procedure rootsFocuser,
@ColorRes int color) {
@@ -153,6 +153,10 @@
final int focusPos = (mScope.lastFocusPosition != RecyclerView.NO_POSITION)
? mScope.lastFocusPosition
: mScope.layout.findFirstVisibleItemPosition();
+ if (focusPos == RecyclerView.NO_POSITION) {
+ return false;
+ }
+
focusItem(focusPos);
return true;
}
@@ -167,7 +171,7 @@
return;
}
- int pos = mScope.adapter.getModelIds().indexOf(mScope.pendingFocusId);
+ int pos = mScope.adapter.getStableIds().indexOf(mScope.pendingFocusId);
if (pos != -1) {
focusItem(pos);
}
@@ -558,7 +562,7 @@
int itemCount = mScope.adapter.getItemCount();
List<String> index = new ArrayList<>(itemCount);
for (int i = 0; i < itemCount; i++) {
- String modelId = mScope.adapter.getModelId(i);
+ String modelId = mScope.adapter.getStableId(i);
Cursor cursor = mScope.model.getItem(modelId);
if (modelId != null && cursor != null) {
String title = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
diff --git a/src/com/android/documentsui/Injector.java b/src/com/android/documentsui/Injector.java
index 30d1d4b..7f9edd4 100644
--- a/src/com/android/documentsui/Injector.java
+++ b/src/com/android/documentsui/Injector.java
@@ -28,11 +28,12 @@
import com.android.documentsui.base.Features;
import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.RootInfo;
+import com.android.documentsui.dirlist.DocsStableIdProvider;
import com.android.documentsui.dirlist.DocumentsAdapter;
import com.android.documentsui.prefs.ScopedPreferences;
import com.android.documentsui.queries.SearchViewManager;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.selection.SelectionManager.SelectionPredicate;
+import com.android.documentsui.selection.ContentLock;
+import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.ui.DialogController;
import com.android.documentsui.ui.MessageBuilder;
import com.android.internal.annotations.VisibleForTesting;
@@ -70,7 +71,7 @@
public FocusManager focusManager;
@ContentScoped
- public SelectionManager selectionMgr;
+ public DocsSelectionHelper selectionMgr;
private final Model mModel;
@@ -119,9 +120,9 @@
return focusManager.reset(view, model);
}
- public SelectionManager getSelectionManager(
- DocumentsAdapter adapter, SelectionPredicate canSetState) {
- return selectionMgr.reset(adapter, canSetState);
+ public SelectionHelper getSelectionManager(
+ DocumentsAdapter adapter, SelectionHelper.SelectionPredicate canSetState) {
+ return selectionMgr.reset(adapter, new DocsStableIdProvider(adapter), canSetState);
}
public final ActionModeController getActionModeController(
@@ -131,20 +132,22 @@
/**
* Obtains action handler and resets it if necessary.
- * @param reloadLock the lock held by {@link com.android.documentsui.selection.BandController}
- * to prevent loader from updating result during band selection. May be
- * {@code null} if called from
- * {@link com.android.documentsui.sidebar.RootsFragment}.
+ *
+ * @param contentLock the lock held by
+ * {@link com.android.documentsui.selection.BandSelectionHelper} and
+ * {@link com.android.documentsui.selection.GestureSelectionHelper} to prevent
+ * loader from updating result during band/gesture selection. May be {@code null} if
+ * called from {@link com.android.documentsui.sidebar.RootsFragment}.
* @return the action handler
*/
- public T getActionHandler(@Nullable DirectoryReloadLock reloadLock) {
+ public T getActionHandler(@Nullable ContentLock contentLock) {
// provide our friend, RootsFragment, early access to this special feature!
- if (reloadLock == null) {
+ if (contentLock == null) {
return actions;
}
- return actions.reset(reloadLock);
+ return actions.reset(contentLock);
}
/**
diff --git a/src/com/android/documentsui/LoadDocStackTask.java b/src/com/android/documentsui/LoadDocStackTask.java
index 1ce4630..af10693 100644
--- a/src/com/android/documentsui/LoadDocStackTask.java
+++ b/src/com/android/documentsui/LoadDocStackTask.java
@@ -60,7 +60,6 @@
@Override
public @Nullable DocumentStack run(Uri... uris) {
- // assert(Features.OMC_RUNTIME);
if (mDocs.isDocumentUri(uris[0])) {
final Uri docUri;
if (DocumentsContract.isTreeUri(uris[0])) {
diff --git a/src/com/android/documentsui/MenuManager.java b/src/com/android/documentsui/MenuManager.java
index a8c9767..01e4619 100644
--- a/src/com/android/documentsui/MenuManager.java
+++ b/src/com/android/documentsui/MenuManager.java
@@ -62,8 +62,8 @@
updateCopyTo(menu.findItem(R.id.action_menu_copy_to), selection);
updateCompress(menu.findItem(R.id.action_menu_compress), selection);
updateExtractTo(menu.findItem(R.id.action_menu_extract_to), selection);
+ updateInspect(menu.findItem(R.id.action_menu_inspect), selection);
updateViewInOwner(menu.findItem(R.id.action_menu_view_in_owner), selection);
- updateInspector(menu.findItem(R.id.action_menu_inspector), selection);
Menus.disableHiddenItems(menu);
}
@@ -78,7 +78,7 @@
menu.findItem(R.id.option_menu_list));
updateAdvanced(menu.findItem(R.id.option_menu_advanced));
updateDebug(menu.findItem(R.id.option_menu_debug));
-
+ updateInspect(menu.findItem(R.id.option_menu_inspect));
Menus.disableHiddenItems(menu);
}
@@ -115,7 +115,7 @@
*/
@VisibleForTesting
public void updateContextMenuForFiles(Menu menu, SelectionDetails selectionDetails) {
- assert(selectionDetails != null);
+ assert selectionDetails != null;
MenuItem share = menu.findItem(R.id.dir_menu_share);
MenuItem open = menu.findItem(R.id.dir_menu_open);
@@ -144,7 +144,7 @@
*/
@VisibleForTesting
public void updateContextMenuForDirs(Menu menu, SelectionDetails selectionDetails) {
- assert(selectionDetails != null);
+ assert selectionDetails != null;
MenuItem openInNewWindow = menu.findItem(R.id.dir_menu_open_in_new_window);
MenuItem rename = menu.findItem(R.id.dir_menu_rename);
@@ -164,11 +164,12 @@
*/
@VisibleForTesting
public void updateContextMenu(Menu menu, SelectionDetails selectionDetails) {
- assert(selectionDetails != null);
+ assert selectionDetails != null;
MenuItem cut = menu.findItem(R.id.dir_menu_cut_to_clipboard);
MenuItem copy = menu.findItem(R.id.dir_menu_copy_to_clipboard);
MenuItem delete = menu.findItem(R.id.dir_menu_delete);
+ MenuItem inspect = menu.findItem(R.id.dir_menu_inspect);
final boolean canCopy =
selectionDetails.size() > 0 && !selectionDetails.containsPartialFiles();
@@ -176,6 +177,8 @@
cut.setEnabled(canCopy && canDelete);
copy.setEnabled(canCopy);
delete.setEnabled(canDelete);
+
+ inspect.setEnabled(selectionDetails.size() == 1);
}
/**
@@ -188,10 +191,12 @@
MenuItem paste = menu.findItem(R.id.dir_menu_paste_from_clipboard);
MenuItem selectAll = menu.findItem(R.id.dir_menu_select_all);
MenuItem createDir = menu.findItem(R.id.dir_menu_create_dir);
+ MenuItem inspect = menu.findItem(R.id.dir_menu_inspect);
paste.setEnabled(mDirDetails.hasItemsToPaste() && mDirDetails.canCreateDoc());
updateSelectAll(selectAll);
updateCreateDir(createDir);
+ updateInspect(inspect);
}
/**
@@ -273,8 +278,19 @@
rename.setVisible(false);
}
- protected void updateInspector(MenuItem properties, SelectionDetails selectionDetails) {
- properties.setVisible(false);
+ /**
+ * This method is called for standard activity option menu as opposed
+ * to when there is a selection.
+ */
+ protected void updateInspect(MenuItem inspector) {
+ inspector.setVisible(false);
+ }
+
+ /**
+ * This method is called for action mode, when a selection exists.
+ */
+ protected void updateInspect(MenuItem inspect, SelectionDetails selectionDetails) {
+ inspect.setVisible(false);
}
protected void updateViewInOwner(MenuItem view, SelectionDetails selectionDetails) {
diff --git a/src/com/android/documentsui/Metrics.java b/src/com/android/documentsui/Metrics.java
index f421906..b7f756f 100644
--- a/src/com/android/documentsui/Metrics.java
+++ b/src/com/android/documentsui/Metrics.java
@@ -16,14 +16,11 @@
package com.android.documentsui;
-import static android.os.Environment.STANDARD_DIRECTORIES;
import static com.android.documentsui.DocumentsApplication.acquireUnstableProviderOrThrow;
import static com.android.documentsui.base.Shared.DEBUG;
import android.annotation.IntDef;
import android.annotation.Nullable;
-import android.annotation.StringDef;
-import android.app.Activity;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
@@ -45,13 +42,14 @@
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
-/** @hide */
+/**
+ * Methods for logging metrics.
+ */
public final class Metrics {
private static final String TAG = "Metrics";
@@ -689,102 +687,6 @@
logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA));
}
- // Types for logInvalidScopedAccessRequest
- public static final String SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS =
- "docsui_scoped_directory_access_invalid_args";
- public static final String SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY =
- "docsui_scoped_directory_access_invalid_dir";
- public static final String SCOPED_DIRECTORY_ACCESS_ERROR =
- "docsui_scoped_directory_access_error";
-
- @StringDef(value = {
- SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS,
- SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY,
- SCOPED_DIRECTORY_ACCESS_ERROR
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface InvalidScopedAccess{}
-
- public static void logInvalidScopedAccessRequest(Context context,
- @InvalidScopedAccess String type) {
- switch (type) {
- case SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS:
- case SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY:
- case SCOPED_DIRECTORY_ACCESS_ERROR:
- logCount(context, type);
- break;
- default:
- Log.wtf(TAG, "invalid InvalidScopedAccess: " + type);
- }
- }
-
- // Types for logValidScopedAccessRequest
- public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
- public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
- public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
- public static final int SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST = 3;
- public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED = 4;
-
- @IntDef(flag = true, value = {
- SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
- SCOPED_DIRECTORY_ACCESS_GRANTED,
- SCOPED_DIRECTORY_ACCESS_DENIED,
- SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST,
- SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ScopedAccessGrant {}
-
- public static void logValidScopedAccessRequest(Activity activity, String directory,
- @ScopedAccessGrant int type) {
- int index = -1;
- if (OpenExternalDirectoryActivity.DIRECTORY_ROOT.equals(directory)) {
- index = -2;
- } else {
- for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
- if (STANDARD_DIRECTORIES[i].equals(directory)) {
- index = i;
- break;
- }
- }
- }
- final String packageName = activity.getCallingPackage();
- switch (type) {
- case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, packageName);
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
- break;
- case SCOPED_DIRECTORY_ACCESS_GRANTED:
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
- break;
- case SCOPED_DIRECTORY_ACCESS_DENIED:
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
- break;
- case SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST:
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE, packageName);
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER, index);
- break;
- case SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED:
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE, packageName);
- MetricsLogger.action(activity, MetricsEvent
- .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER, index);
- break;
- default:
- Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
- }
- }
-
/**
* Logs the action that was started by user.
* @param context
diff --git a/src/com/android/documentsui/PackageReceiver.java b/src/com/android/documentsui/PackageReceiver.java
index 5cb2827..e917369 100644
--- a/src/com/android/documentsui/PackageReceiver.java
+++ b/src/com/android/documentsui/PackageReceiver.java
@@ -23,10 +23,11 @@
import android.net.Uri;
import com.android.documentsui.picker.LastAccessedProvider;
-import com.android.documentsui.prefs.LocalPreferences;
+import com.android.documentsui.prefs.ScopedAccessLocalPreferences;
/**
- * Clean up {@link LastAccessedProvider} and {@link LocalPreferences} when packages are removed.
+ * Clean up {@link LastAccessedProvider} and {@link ScopedAccessLocalPreferences} when packages
+ * are removed.
*/
public class PackageReceiver extends BroadcastReceiver {
@Override
@@ -44,7 +45,7 @@
null,
null);
if (packageName != null) {
- LocalPreferences.clearPackagePreferences(context, packageName);
+ ScopedAccessLocalPreferences.clearPackagePreferences(context, packageName);
}
} else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
if (packageName != null) {
@@ -52,7 +53,7 @@
LastAccessedProvider.buildLastAccessed(packageName),
LastAccessedProvider.METHOD_PURGE_PACKAGE,
packageName, null);
- LocalPreferences.clearPackagePreferences(context, packageName);
+ ScopedAccessLocalPreferences.clearPackagePreferences(context, packageName);
}
}
}
diff --git a/src/com/android/documentsui/RootsMonitor.java b/src/com/android/documentsui/RootsMonitor.java
index 82b3781..f1200ed 100644
--- a/src/com/android/documentsui/RootsMonitor.java
+++ b/src/com/android/documentsui/RootsMonitor.java
@@ -32,7 +32,6 @@
import com.android.documentsui.dirlist.AnimationView;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.roots.ProvidersAccess;
-import com.android.documentsui.selection.SelectionManager;
import java.util.Collection;
@@ -57,7 +56,7 @@
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- new HandleRootsChangedTask<T>(
+ new HandleRootsChangedTask<>(
activity,
actions,
providers,
diff --git a/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/src/com/android/documentsui/ScopedAccessActivity.java
similarity index 90%
rename from src/com/android/documentsui/OpenExternalDirectoryActivity.java
rename to src/com/android/documentsui/ScopedAccessActivity.java
index 74af224..386e8da 100644
--- a/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/src/com/android/documentsui/ScopedAccessActivity.java
@@ -19,21 +19,21 @@
import static android.os.Environment.isStandardDirectory;
import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME;
import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS;
-import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY;
-import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
-import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
-import static com.android.documentsui.base.Shared.DEBUG;
-import static com.android.documentsui.prefs.LocalPreferences.PERMISSION_ASK_AGAIN;
-import static com.android.documentsui.prefs.LocalPreferences.PERMISSION_NEVER_ASK;
-import static com.android.documentsui.prefs.LocalPreferences.getScopedAccessPermissionStatus;
-import static com.android.documentsui.prefs.LocalPreferences.setScopedAccessPermissionStatus;
+import static com.android.documentsui.ScopedAccessMetrics.DEBUG;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_DENIED;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_ERROR;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_GRANTED;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS;
+import static com.android.documentsui.ScopedAccessMetrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY;
+import static com.android.documentsui.ScopedAccessMetrics.logInvalidScopedAccessRequest;
+import static com.android.documentsui.ScopedAccessMetrics.logValidScopedAccessRequest;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.PERMISSION_ASK_AGAIN;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.PERMISSION_NEVER_ASK;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.getScopedAccessPermissionStatus;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.setScopedAccessPermissionStatus;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -75,10 +75,10 @@
import java.util.List;
/**
- * Activity responsible for handling {@link Intent#ACTION_OPEN_EXTERNAL_DOCUMENT}.
+ * Activity responsible for handling {@link StorageVolume#createAccessIntent(String)}.
*/
-public class OpenExternalDirectoryActivity extends Activity {
- private static final String TAG = "OpenExternalDirectory";
+public class ScopedAccessActivity extends Activity {
+ private static final String TAG = "ScopedAccessActivity";
private static final String FM_TAG = "open_external_directory";
private static final String EXTRA_FILE = "com.android.documentsui.FILE";
private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL";
@@ -151,7 +151,7 @@
* Validates the given path (volume + directory) and display the appropriate dialog asking the
* user to grant access to it.
*/
- private static boolean showFragment(OpenExternalDirectoryActivity activity, int userId,
+ private static boolean showFragment(ScopedAccessActivity activity, int userId,
StorageVolume storageVolume, String directoryName) {
if (DEBUG)
Log.d(TAG, "showFragment() for volume " + storageVolume.dump() + ", directory "
@@ -228,7 +228,7 @@
}
// Checks if the user has granted the permission already.
- final Intent intent = getIntentForExistingPermission(activity, isRoot, internalRoot, file);
+ final Intent intent = getIntentForExistingPermission(activity, internalRoot, file);
if (intent != null) {
logValidScopedAccessRequest(activity, directory,
SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED);
@@ -261,8 +261,7 @@
final FragmentManager fm = activity.getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
- final OpenExternalDirectoryDialogFragment fragment =
- new OpenExternalDirectoryDialogFragment();
+ final ScopedAccessDialogFragment fragment = new ScopedAccessDialogFragment();
fragment.setArguments(args);
ft.add(fragment, FM_TAG);
ft.commitAllowingStateLoss();
@@ -341,8 +340,8 @@
return intent;
}
- private static Intent getIntentForExistingPermission(OpenExternalDirectoryActivity activity,
- boolean isRoot, File root, File file) {
+ private static Intent getIntentForExistingPermission(ScopedAccessActivity activity, File root,
+ File file) {
final String packageName = activity.getCallingPackage();
final ContentProviderClient storageClient = activity.getExternalStorageClient();
final Uri grantedUri = getGrantedUriPermission(activity, storageClient, file);
@@ -369,7 +368,7 @@
return null;
}
- public static class OpenExternalDirectoryDialogFragment extends DialogFragment {
+ public static class ScopedAccessDialogFragment extends DialogFragment {
private File mFile;
private String mVolumeUuid;
@@ -378,7 +377,7 @@
private boolean mIsRoot;
private boolean mIsPrimary;
private CheckBox mDontAskAgain;
- private OpenExternalDirectoryActivity mActivity;
+ private ScopedAccessActivity mActivity;
private AlertDialog mDialog;
@Override
@@ -394,7 +393,7 @@
mIsRoot = args.getBoolean(EXTRA_IS_ROOT);
mIsPrimary= args.getBoolean(EXTRA_IS_PRIMARY);
}
- mActivity = (OpenExternalDirectoryActivity) getActivity();
+ mActivity = (ScopedAccessActivity) getActivity();
}
@Override
@@ -416,7 +415,7 @@
// Sanity check.
Log.wtf(TAG, "activity references don't match on onCreateDialog(): mActivity = "
+ mActivity + " , getActivity() = " + getActivity());
- mActivity = (OpenExternalDirectoryActivity) getActivity();
+ mActivity = (ScopedAccessActivity) getActivity();
}
final String directory = mFile.getName();
final String directoryName = mIsRoot ? DIRECTORY_ROOT : directory;
diff --git a/src/com/android/documentsui/ScopedAccessMetrics.java b/src/com/android/documentsui/ScopedAccessMetrics.java
new file mode 100644
index 0000000..177150e
--- /dev/null
+++ b/src/com/android/documentsui/ScopedAccessMetrics.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static android.os.Environment.STANDARD_DIRECTORIES;
+
+import android.annotation.IntDef;
+import android.annotation.StringDef;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Methods for logging scoped directory access metrics.
+ */
+public final class ScopedAccessMetrics {
+ private static final String TAG = "Metrics";
+
+ public static final boolean DEBUG = Build.IS_DEBUGGABLE;
+
+ // Types for logInvalidScopedAccessRequest
+ public static final String SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS =
+ "docsui_scoped_directory_access_invalid_args";
+ public static final String SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY =
+ "docsui_scoped_directory_access_invalid_dir";
+ public static final String SCOPED_DIRECTORY_ACCESS_ERROR =
+ "docsui_scoped_directory_access_error";
+
+ @StringDef(value = {
+ SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS,
+ SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY,
+ SCOPED_DIRECTORY_ACCESS_ERROR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InvalidScopedAccess{}
+
+ public static void logInvalidScopedAccessRequest(Context context,
+ @InvalidScopedAccess String type) {
+ switch (type) {
+ case SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS:
+ case SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY:
+ case SCOPED_DIRECTORY_ACCESS_ERROR:
+ logCount(context, type);
+ break;
+ default:
+ Log.wtf(TAG, "invalid InvalidScopedAccess: " + type);
+ }
+ }
+
+ // Types for logValidScopedAccessRequest
+ public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
+ public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
+ public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
+ public static final int SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST = 3;
+ public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED = 4;
+
+ @IntDef(flag = true, value = {
+ SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
+ SCOPED_DIRECTORY_ACCESS_GRANTED,
+ SCOPED_DIRECTORY_ACCESS_DENIED,
+ SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST,
+ SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ScopedAccessGrant {}
+
+ public static void logValidScopedAccessRequest(Activity activity, String directory,
+ @ScopedAccessGrant int type) {
+ int index = -1;
+ if (ScopedAccessActivity.DIRECTORY_ROOT.equals(directory)) {
+ index = -2;
+ } else {
+ for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
+ if (STANDARD_DIRECTORIES[i].equals(directory)) {
+ index = i;
+ break;
+ }
+ }
+ }
+ final String packageName = activity.getCallingPackage();
+ switch (type) {
+ case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, packageName);
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
+ break;
+ case SCOPED_DIRECTORY_ACCESS_GRANTED:
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
+ break;
+ case SCOPED_DIRECTORY_ACCESS_DENIED:
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
+ break;
+ case SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST:
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE, packageName);
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER, index);
+ break;
+ case SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED:
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE, packageName);
+ MetricsLogger.action(activity, MetricsEvent
+ .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER, index);
+ break;
+ default:
+ Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
+ }
+ }
+
+ /**
+ * Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
+ *
+ * @param context
+ * @param name The counter to increment.
+ */
+ private static void logCount(Context context, String name) {
+ if (DEBUG) Log.d(TAG, name + ": " + 1);
+ MetricsLogger.count(context, name, 1);
+ }
+}
diff --git a/src/com/android/documentsui/ScopedAccessPackageReceiver.java b/src/com/android/documentsui/ScopedAccessPackageReceiver.java
new file mode 100644
index 0000000..995eedc
--- /dev/null
+++ b/src/com/android/documentsui/ScopedAccessPackageReceiver.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.documentsui.prefs.ScopedAccessLocalPreferences;
+
+/**
+ * Clean up {@link ScopedAccessLocalPreferences} when packages are removed.
+ */
+public class ScopedAccessPackageReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final Uri data = intent.getData();
+ final String packageName = data == null ? null : data.getSchemeSpecificPart();
+
+ if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
+ if (packageName != null) {
+ ScopedAccessLocalPreferences.clearPackagePreferences(context, packageName);
+ }
+ } else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
+ if (packageName != null) {
+ ScopedAccessLocalPreferences.clearPackagePreferences(context, packageName);
+ }
+ }
+ }
+}
diff --git a/src/com/android/documentsui/ScopedAccessProvider.java b/src/com/android/documentsui/ScopedAccessProvider.java
new file mode 100644
index 0000000..2fcbe45
--- /dev/null
+++ b/src/com/android/documentsui/ScopedAccessProvider.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui;
+
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES_COLUMNS;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COLUMNS;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_DIRECTORY;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_GRANTED;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_PACKAGE;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_VOLUME_UUID;
+
+import static com.android.documentsui.ScopedAccessMetrics.DEBUG;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.PERMISSION_ASK_AGAIN;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.PERMISSION_NEVER_ASK;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.getAllPackages;
+import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.getAllPermissions;
+
+import android.app.ActivityManager;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.documentsui.prefs.ScopedAccessLocalPreferences.Permission;
+import com.android.internal.util.ArrayUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Provider used to manage scoped access directory permissions.
+ *
+ * <p>It fetches data from 2 sources:
+ *
+ * <ul>
+ * <li>{@link com.android.documentsui.prefs.ScopedAccessLocalPreferences} for denied permissions.
+ * <li>{@link ActivityManager} for allowed permissions.
+ * </ul>
+ *
+ * <p>And returns the results in 2 tables:
+ *
+ * <ul>
+ * <li>{@link #TABLE_PACKAGES}: read-only table with the name of all packages
+ * (column ({@link android.os.storage.StorageVolume.ScopedAccessProviderContract#COL_PACKAGE}) that
+ * had a scoped access directory permission granted or denied.
+ * <li>{@link #TABLE_PERMISSIONS}: writable table with the name of all packages
+ * (column ({@link android.os.storage.StorageVolume.ScopedAccessProviderContract#COL_PACKAGE}) that
+ * had a scoped access directory
+ * (column ({@link android.os.storage.StorageVolume.ScopedAccessProviderContract#COL_DIRECTORY})
+ * permission for a volume (column
+ * {@link android.os.storage.StorageVolume.ScopedAccessProviderContract#COL_VOLUME_UUID}, which
+ * contains the volume UUID or {@code null} if it's the primary partition) granted or denied
+ * (column ({@link android.os.storage.StorageVolume.ScopedAccessProviderContract#COL_GRANTED}).
+ * </ul>
+ *
+ * <p><b>Note:</b> the {@code query()} methods return all entries; it does not support selection or
+ * projections.
+ */
+// TODO(b/63720392): add unit tests
+public class ScopedAccessProvider extends ContentProvider {
+
+ private static final String TAG = "ScopedAccessProvider";
+ private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ private static final int URI_PACKAGES = 1;
+ private static final int URI_PERMISSIONS = 2;
+
+ public static final String AUTHORITY = "com.android.documentsui.scopedAccess";
+
+ static {
+ sMatcher.addURI(AUTHORITY, TABLE_PACKAGES + "/*", URI_PACKAGES);
+ sMatcher.addURI(AUTHORITY, TABLE_PERMISSIONS + "/*", URI_PERMISSIONS);
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ if (DEBUG) {
+ Log.v(TAG, "query(" + uri + "): proj=" + Arrays.toString(projection)
+ + ", sel=" + selection);
+ }
+ switch (sMatcher.match(uri)) {
+ case URI_PACKAGES:
+ return getPackagesCursor();
+ case URI_PERMISSIONS:
+ return getPermissionsCursor();
+ default:
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+ }
+
+ private Cursor getPackagesCursor() {
+ // First get the packages that were denied
+ final ArraySet<String> pkgs = getAllPackages(getContext());
+
+ if (ArrayUtils.isEmpty(pkgs)) {
+ if (DEBUG) Log.v(TAG, "getPackagesCursor(): ignoring " + pkgs);
+ return null;
+ }
+
+ // TODO(b/63720392): also need to query AM for granted permissions
+
+ // Then create the cursor
+ final MatrixCursor cursor = new MatrixCursor(TABLE_PACKAGES_COLUMNS, pkgs.size());
+ final Object[] column = new Object[1];
+ for (int i = 0; i < pkgs.size(); i++) {
+ final String pkg = pkgs.valueAt(i);
+ column[0] = pkg;
+ cursor.addRow(column);
+ }
+
+ return cursor;
+ }
+
+ // TODO(b/63720392): decide how to handle ROOT_DIRECTORY - convert to null?
+ private Cursor getPermissionsCursor() {
+ // First get the packages that were denied
+ final ArrayList<Permission> rawPermissions = getAllPermissions(getContext());
+
+ if (ArrayUtils.isEmpty(rawPermissions)) {
+ if (DEBUG) Log.v(TAG, "getPermissionsCursor(): ignoring " + rawPermissions);
+ return null;
+ }
+
+ final List<Object[]> permissions = rawPermissions.stream()
+ .filter(permission -> permission.status == PERMISSION_ASK_AGAIN
+ || permission.status == PERMISSION_NEVER_ASK)
+ .map(permission ->
+ new Object[] { permission.pkg, permission.uuid, permission.directory,
+ Integer.valueOf(1) })
+ .collect(Collectors.toList());
+
+ // TODO(b/63720392): also need to query AM for granted permissions
+
+ // Then create the cursor
+ final MatrixCursor cursor = new MatrixCursor(TABLE_PERMISSIONS_COLUMNS, permissions.size());
+ for (int i = 0; i < permissions.size(); i++) {
+ cursor.addRow(permissions.get(i));
+ }
+ return cursor;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ if (sMatcher.match(uri) != URI_PERMISSIONS) {
+ throw new UnsupportedOperationException("insert(): unsupported " + uri);
+ }
+
+ if (DEBUG) Log.v(TAG, "insert(" + uri + "): " + values);
+
+ // TODO(b/63720392): implement
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ if (sMatcher.match(uri) != URI_PERMISSIONS) {
+ throw new UnsupportedOperationException("delete(): unsupported " + uri);
+ }
+
+ if (DEBUG) Log.v(TAG, "delete(" + uri + "): " + selection);
+
+ // TODO(b/63720392): implement
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ if (sMatcher.match(uri) != URI_PERMISSIONS) {
+ throw new UnsupportedOperationException("update(): unsupported " + uri);
+ }
+
+ if (DEBUG) Log.v(TAG, "update(" + uri + "): " + selection + " = " + values);
+
+ // TODO(b/63720392): implement
+ return 0;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ final String prefix = " ";
+
+ pw.print("Packages: ");
+ try (Cursor cursor = getPackagesCursor()) {
+ if (cursor == null) {
+ pw.println("N/A");
+ } else {
+ pw.println(cursor.getCount());
+ while (cursor.moveToNext()) {
+ pw.print(prefix); pw.println(cursor.getString(0));
+ }
+ }
+ }
+
+ pw.print("Permissions: ");
+ try (Cursor cursor = getPermissionsCursor()) {
+ if (cursor == null) {
+ pw.println("N/A");
+ } else {
+ pw.println(cursor.getCount());
+ while (cursor.moveToNext()) {
+ pw.print(prefix); pw.print(cursor.getString(TABLE_PERMISSIONS_COL_PACKAGE));
+ pw.print('/');
+ final String uuid = cursor.getString(TABLE_PERMISSIONS_COL_VOLUME_UUID);
+ if (uuid != null) {
+ pw.print(uuid); pw.print('>');
+ }
+ pw.print(cursor.getString(TABLE_PERMISSIONS_COL_DIRECTORY));
+ pw.print(": "); pw.println(cursor.getInt(TABLE_PERMISSIONS_COL_GRANTED) == 1);
+ }
+ }
+ }
+
+ pw.print("Raw permissions: ");
+ final ArrayList<Permission> rawPermissions = getAllPermissions(getContext());
+ if (rawPermissions.isEmpty()) {
+ pw.println("N/A");
+ } else {
+ final int size = rawPermissions.size();
+ pw.println(size);
+ for (int i = 0; i < size; i++) {
+ final Permission permission = rawPermissions.get(i);
+ pw.print(prefix); pw.println(permission);
+ }
+ }
+ }
+}
diff --git a/src/com/android/documentsui/SharedInputHandler.java b/src/com/android/documentsui/SharedInputHandler.java
index f3f2641..68772ab 100644
--- a/src/com/android/documentsui/SharedInputHandler.java
+++ b/src/com/android/documentsui/SharedInputHandler.java
@@ -24,7 +24,7 @@
import com.android.documentsui.base.Features;
import com.android.documentsui.base.Procedure;
import com.android.documentsui.dirlist.FocusHandler;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.SelectionHelper;
public class SharedInputHandler {
@@ -34,11 +34,11 @@
private final Procedure mSearchCanceler;
private final Procedure mDirPopper;
private final Features mFeatures;
- private final SelectionManager mSelectionMgr;
+ private final SelectionHelper mSelectionMgr;
public SharedInputHandler(
FocusHandler focusHandler,
- SelectionManager selectionMgr,
+ SelectionHelper selectionMgr,
Procedure searchCanceler,
Procedure dirPopper,
Features features) {
diff --git a/src/com/android/documentsui/archives/Archive.java b/src/com/android/documentsui/archives/Archive.java
index e3c81e3..14d703c 100644
--- a/src/com/android/documentsui/archives/Archive.java
+++ b/src/com/android/documentsui/archives/Archive.java
@@ -26,6 +26,7 @@
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
+import android.provider.MetadataReader;
import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
import android.system.ErrnoException;
@@ -281,7 +282,10 @@
final String mimeType = getMimeTypeForEntry(entry);
row.add(Document.COLUMN_MIME_TYPE, mimeType);
- final int flags = mimeType.startsWith("image/") ? Document.FLAG_SUPPORTS_THUMBNAIL : 0;
+ int flags = mimeType.startsWith("image/") ? Document.FLAG_SUPPORTS_THUMBNAIL : 0;
+ if (MetadataReader.isSupportedMimeType(mimeType)) {
+ flags |= Document.FLAG_SUPPORTS_METADATA;
+ }
row.add(Document.COLUMN_FLAGS, flags);
}
diff --git a/src/com/android/documentsui/archives/ArchivesProvider.java b/src/com/android/documentsui/archives/ArchivesProvider.java
index 8f0e399..508a1aa 100644
--- a/src/com/android/documentsui/archives/ArchivesProvider.java
+++ b/src/com/android/documentsui/archives/ArchivesProvider.java
@@ -17,38 +17,34 @@
package com.android.documentsui.archives;
import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.content.res.Configuration;
-import android.database.ContentObserver;
import android.database.Cursor;
-import android.database.MatrixCursor.RowBuilder;
import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
import android.graphics.Point;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
-import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
+import android.provider.MetadataReader;
import android.support.annotation.Nullable;
import android.util.Log;
import com.android.documentsui.R;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
-import java.io.Closeable;
-import java.io.File;
+import libcore.io.IoUtils;
+
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
-import java.util.concurrent.locks.Lock;
/**
* Provides basic implementation for creating, extracting and accessing
@@ -71,7 +67,7 @@
};
@GuardedBy("mArchives")
- private final Map<Key, Loader> mArchives = new HashMap<Key, Loader>();
+ private final Map<Key, Loader> mArchives = new HashMap<>();
@Override
public Bundle call(String method, String arg, Bundle extras) {
@@ -153,6 +149,32 @@
}
@Override
+ public @Nullable Bundle getDocumentMetadata(String documentId)
+ throws FileNotFoundException {
+
+ final Archive archive = getLoaderOrThrow(documentId).get();
+ final String mimeType = archive.getDocumentType(documentId);
+
+ if (!MetadataReader.isSupportedMimeType(mimeType)) {
+ return null;
+ }
+
+ InputStream stream = null;
+ try {
+ stream = new ParcelFileDescriptor.AutoCloseInputStream(
+ openDocument(documentId, "r", null));
+ final Bundle metadata = new Bundle();
+ MetadataReader.getMetadata(metadata, stream, mimeType, null);
+ return metadata;
+ } catch (IOException e) {
+ Log.e(TAG, "An error occurred retrieving the metadata.", e);
+ return null;
+ } finally {
+ IoUtils.closeQuietly(stream);
+ }
+ }
+
+ @Override
public Cursor queryDocument(String documentId, @Nullable String[] projection)
throws FileNotFoundException {
final ArchiveId archiveId = ArchiveId.fromDocumentId(documentId);
diff --git a/src/com/android/documentsui/base/DocumentInfo.java b/src/com/android/documentsui/base/DocumentInfo.java
index 5d9a93c..a13ad98 100644
--- a/src/com/android/documentsui/base/DocumentInfo.java
+++ b/src/com/android/documentsui/base/DocumentInfo.java
@@ -223,6 +223,7 @@
+ ", isDeleteSupported=" + isDeleteSupported()
+ ", isCreateSupported=" + isCreateSupported()
+ ", isRenameSupported=" + isRenameSupported()
+ + ", isMetadataSupported=" + isMetadataSupported()
+ "} @ "
+ derivedUri;
}
@@ -231,30 +232,30 @@
return (flags & Document.FLAG_DIR_SUPPORTS_CREATE) != 0;
}
- public boolean isDirectory() {
- return Document.MIME_TYPE_DIR.equals(mimeType);
- }
-
- public boolean isWriteSupported() {
- return (flags & Document.FLAG_SUPPORTS_WRITE) != 0;
- }
-
public boolean isDeleteSupported() {
return (flags & Document.FLAG_SUPPORTS_DELETE) != 0;
}
- public boolean isRemoveSupported() {
- return (flags & Document.FLAG_SUPPORTS_REMOVE) != 0;
+ public boolean isMetadataSupported() {
+ return (flags & Document.FLAG_SUPPORTS_METADATA) != 0;
}
public boolean isMoveSupported() {
return (flags & Document.FLAG_SUPPORTS_MOVE) != 0;
}
+ public boolean isRemoveSupported() {
+ return (flags & Document.FLAG_SUPPORTS_REMOVE) != 0;
+ }
+
public boolean isRenameSupported() {
return (flags & Document.FLAG_SUPPORTS_RENAME) != 0;
}
+ public boolean isSettingsSupported() {
+ return (flags & Document.FLAG_SUPPORTS_SETTINGS) != 0;
+ }
+
public boolean isThumbnailSupported() {
return (flags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
}
@@ -263,6 +264,14 @@
return (flags & Document.FLAG_WEB_LINKABLE) != 0;
}
+ public boolean isWriteSupported() {
+ return (flags & Document.FLAG_SUPPORTS_WRITE) != 0;
+ }
+
+ public boolean isDirectory() {
+ return Document.MIME_TYPE_DIR.equals(mimeType);
+ }
+
public boolean isArchive() {
return ArchivesProvider.isSupportedArchiveType(mimeType);
}
@@ -284,10 +293,6 @@
return (flags & Document.FLAG_VIRTUAL_DOCUMENT) != 0;
}
- public boolean isSettingsSupported() {
- return (flags & Document.FLAG_SUPPORTS_SETTINGS) != 0;
- }
-
public boolean prefersSortByLastModified() {
return (flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0;
}
diff --git a/src/com/android/documentsui/base/DocumentStack.java b/src/com/android/documentsui/base/DocumentStack.java
index 9b0605c..090bcb1 100644
--- a/src/com/android/documentsui/base/DocumentStack.java
+++ b/src/com/android/documentsui/base/DocumentStack.java
@@ -17,6 +17,7 @@
package com.android.documentsui.base;
import static com.android.documentsui.base.Shared.DEBUG;
+import static com.android.internal.util.Preconditions.checkArgument;
import android.content.ContentResolver;
import android.database.Cursor;
@@ -123,13 +124,10 @@
}
public void push(DocumentInfo info) {
- boolean alreadyInStack = mList.contains(info);
- assert (!alreadyInStack);
- if (!alreadyInStack) {
- if (DEBUG) Log.d(TAG, "Adding doc to stack: " + info);
- mList.addLast(info);
- mStackTouched = true;
- }
+ checkArgument(!mList.contains(info));
+ if (DEBUG) Log.d(TAG, "Adding doc to stack: " + info);
+ mList.addLast(info);
+ mStackTouched = true;
}
public DocumentInfo pop() {
diff --git a/src/com/android/documentsui/base/DummyLookup.java b/src/com/android/documentsui/base/DummyLookup.java
new file mode 100644
index 0000000..11a6375
--- /dev/null
+++ b/src/com/android/documentsui/base/DummyLookup.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.base;
+
+/**
+ * Lookup that always returns null.
+ */
+public final class DummyLookup<K, V> implements Lookup<K, V> {
+ @Override
+ public V lookup(K key) {
+ return null;
+ }
+}
diff --git a/src/com/android/documentsui/base/Events.java b/src/com/android/documentsui/base/Events.java
index 67814df..c38f1a4 100644
--- a/src/com/android/documentsui/base/Events.java
+++ b/src/com/android/documentsui/base/Events.java
@@ -16,72 +16,83 @@
package com.android.documentsui.base;
-import static com.android.documentsui.base.Shared.DEBUG;
-
import android.graphics.Point;
-import android.support.v7.widget.RecyclerView;
-import android.util.Log;
-import android.util.Pools;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.documentsui.dirlist.DocumentDetails;
-import com.android.documentsui.dirlist.DocumentHolder;
-
-import javax.annotation.Nullable;
/**
* Utility code for dealing with MotionEvents.
*/
public final class Events {
- /**
- * Returns true if event was triggered by a mouse.
- */
public static boolean isMouseEvent(MotionEvent e) {
- int toolType = e.getToolType(0);
- return toolType == MotionEvent.TOOL_TYPE_MOUSE;
+ return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE;
}
- /**
- * Returns true if event was triggered by a finger or stylus touch.
- */
+ public static boolean isActionMove(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_MOVE;
+ }
+
public static boolean isActionDown(MotionEvent e) {
return e.getActionMasked() == MotionEvent.ACTION_DOWN;
}
- /**
- * Returns true if event was triggered by a finger or stylus touch.
- */
public static boolean isActionUp(MotionEvent e) {
return e.getActionMasked() == MotionEvent.ACTION_UP;
}
- /**
- * Returns true if the shift is pressed.
- */
- public boolean isShiftPressed(MotionEvent e) {
- return hasShiftBit(e.getMetaState());
+ public static boolean isMultiPointerActionDown(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN;
+ }
+
+ public static boolean isMultiPointerActionUp(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_POINTER_UP;
+ }
+
+ public static boolean isActionCancel(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_CANCEL;
+ }
+
+ public static boolean isPrimaryButtonPressed(MotionEvent e) {
+ return e.isButtonPressed(MotionEvent.BUTTON_PRIMARY);
+ }
+
+ public static boolean isSecondaryButtonPressed(MotionEvent e) {
+ return e.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
+ }
+
+ public static boolean isTertiaryButtonPressed(MotionEvent e) {
+ return e.isButtonPressed(MotionEvent.BUTTON_TERTIARY);
+ }
+
+ public static boolean isCtrlKeyPressed(MotionEvent e) {
+ return hasBit(e.getMetaState(), KeyEvent.META_CTRL_ON);
+ }
+
+ public static boolean isAltKeyPressed(MotionEvent e) {
+ return hasBit(e.getMetaState(), KeyEvent.META_ALT_ON);
+ }
+
+ public static boolean isShiftKeyPressed(MotionEvent e) {
+ return hasBit(e.getMetaState(), KeyEvent.META_SHIFT_ON);
+ }
+
+ public static boolean isTouchpadScroll(MotionEvent e) {
+ // Touchpad inputs are treated as mouse inputs, and when scrolling, there are no buttons
+ // returned.
+ return isMouseEvent(e) && isActionMove(e) && e.getButtonState() == 0;
+ }
+
+ private static boolean hasBit(int metaState, int bit) {
+ return (metaState & bit) != 0;
+ }
+
+ public static Point getOrigin(MotionEvent e) {
+ return new Point((int) e.getX(), (int) e.getY());
}
/**
- * Returns true if the event is a mouse drag event.
- * @param e
- * @return
- */
- public static boolean isMouseDragEvent(InputEvent e) {
- return e.isMouseEvent()
- && e.isActionMove()
- && e.isPrimaryButtonPressed()
- && e.isOverDragHotspot();
- }
-
- /**
- * Whether or not the given keyCode represents a navigation keystroke (e.g. up, down, home).
- *
- * @param keyCode
- * @return
+ * @return true if keyCode is a known navigation code (e.g. up, down, home).
*/
public static boolean isNavigationKeyCode(int keyCode) {
switch (keyCode) {
@@ -99,320 +110,14 @@
}
}
-
/**
- * Returns true if the "SHIFT" bit is set.
+ * Returns true if the event is a mouse drag event.
+ * @param e
+ * @return
*/
- public static boolean hasShiftBit(int metaState) {
- return (metaState & KeyEvent.META_SHIFT_ON) != 0;
- }
-
- public static boolean hasCtrlBit(int metaState) {
- return (metaState & KeyEvent.META_CTRL_ON) != 0;
- }
-
- public static boolean hasAltBit(int metaState) {
- return (metaState & KeyEvent.META_ALT_ON) != 0;
- }
-
- /**
- * A facade over MotionEvent primarily designed to permit for unit testing
- * of related code.
- */
- public interface InputEvent extends AutoCloseable {
- boolean isMouseEvent();
- boolean isPrimaryButtonPressed();
- boolean isSecondaryButtonPressed();
- boolean isTertiaryButtonPressed();
- boolean isAltKeyDown();
- boolean isShiftKeyDown();
- boolean isCtrlKeyDown();
-
- /** Returns true if the action is the initial press of a mouse or touch. */
- boolean isActionDown();
-
- /** Returns true if the action is the final release of a mouse or touch. */
- boolean isActionUp();
-
- /**
- * Returns true when the action is the initial press of a non-primary (ex. second finger)
- * pointer.
- * See {@link MotionEvent#ACTION_POINTER_DOWN}.
- */
- boolean isMultiPointerActionDown();
-
- /**
- * Returns true when the action is the final of a non-primary (ex. second finger)
- * pointer.
- * * See {@link MotionEvent#ACTION_POINTER_UP}.
- */
- boolean isMultiPointerActionUp();
-
- /** Returns true if the action is neither the initial nor the final release of a mouse
- * or touch. */
- boolean isActionMove();
-
- /** Returns true if the action is cancel. */
- boolean isActionCancel();
-
- // Eliminate the checked Exception from Autoclosable.
- @Override
- public void close();
-
- Point getOrigin();
- float getX();
- float getY();
- float getRawX();
- float getRawY();
- int getPointerCount();
-
- /** Returns true if there is an item under the finger/cursor. */
- boolean isOverItem();
-
- /**
- * Returns true if there is a model backed item under the finger/cursor.
- * Resulting calls on the event instance should never return a null
- * DocumentDetails and DocumentDetails#hasModelId should always return true
- */
- boolean isOverModelItem();
-
- /**
- * Returns true if the event is over an area that can be dragged via touch.
- * List items have a white area that is not draggable.
- */
- boolean isOverDragHotspot();
-
- /**
- * Returns true if the event is a two/three-finger scroll on touchpad.
- */
- boolean isTouchpadScroll();
-
- /** Returns the adapter position of the item under the finger/cursor. */
- int getItemPosition();
-
- boolean isOverDocIcon();
-
- /** Returns the DocumentDetails for the item under the event, or null. */
- @Nullable DocumentDetails getDocumentDetails();
- }
-
- public static final class MotionInputEvent implements InputEvent {
- private static final String TAG = "MotionInputEvent";
-
- private static final int UNSET_POSITION = RecyclerView.NO_POSITION - 1;
-
- private static final Pools.SimplePool<MotionInputEvent> sPool = new Pools.SimplePool<>(1);
-
- private MotionEvent mEvent;
- private @Nullable RecyclerView mRecView;
-
- private int mPosition = UNSET_POSITION;
- private @Nullable DocumentDetails mDocDetails;
-
- private MotionInputEvent() {
- if (DEBUG) Log.i(TAG, "Created a new instance.");
- }
-
- public static MotionInputEvent obtain(MotionEvent event, RecyclerView view) {
- Shared.checkMainLoop();
-
- MotionInputEvent instance = sPool.acquire();
- instance = (instance != null ? instance : new MotionInputEvent());
-
- instance.mEvent = event;
- instance.mRecView = view;
-
- return instance;
- }
-
- public void recycle() {
- Shared.checkMainLoop();
-
- mEvent = null;
- mRecView = null;
- mPosition = UNSET_POSITION;
- mDocDetails = null;
-
- boolean released = sPool.release(this);
- // This assert is used to guarantee we won't generate too many instances that can't be
- // held in the pool, which indicates our pool size is too small.
- //
- // Right now one instance is enough because we expect all instances are only used in
- // main thread.
- assert(released);
- }
-
- @Override
- public void close() {
- recycle();
- }
-
- @Override
- public boolean isMouseEvent() {
- return Events.isMouseEvent(mEvent);
- }
-
- @Override
- public boolean isPrimaryButtonPressed() {
- return mEvent.isButtonPressed(MotionEvent.BUTTON_PRIMARY);
- }
-
- @Override
- public boolean isSecondaryButtonPressed() {
- return mEvent.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
- }
-
- @Override
- public boolean isTertiaryButtonPressed() {
- return mEvent.isButtonPressed(MotionEvent.BUTTON_TERTIARY);
- }
-
- @Override
- public boolean isAltKeyDown() {
- return Events.hasAltBit(mEvent.getMetaState());
- }
-
- @Override
- public boolean isShiftKeyDown() {
- return Events.hasShiftBit(mEvent.getMetaState());
- }
-
- @Override
- public boolean isCtrlKeyDown() {
- return Events.hasCtrlBit(mEvent.getMetaState());
- }
-
- @Override
- public boolean isActionDown() {
- return mEvent.getActionMasked() == MotionEvent.ACTION_DOWN;
- }
-
- @Override
- public boolean isActionUp() {
- return mEvent.getActionMasked() == MotionEvent.ACTION_UP;
- }
-
- @Override
- public boolean isMultiPointerActionDown() {
- return mEvent.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN;
- }
-
- @Override
- public boolean isMultiPointerActionUp() {
- return mEvent.getActionMasked() == MotionEvent.ACTION_POINTER_UP;
- }
-
-
- @Override
- public boolean isActionMove() {
- return mEvent.getActionMasked() == MotionEvent.ACTION_MOVE;
- }
-
- @Override
- public boolean isActionCancel() {
- return mEvent.getActionMasked() == MotionEvent.ACTION_CANCEL;
- }
-
- @Override
- public Point getOrigin() {
- return new Point((int) mEvent.getX(), (int) mEvent.getY());
- }
-
- @Override
- public float getX() {
- return mEvent.getX();
- }
-
- @Override
- public float getY() {
- return mEvent.getY();
- }
-
- @Override
- public float getRawX() {
- return mEvent.getRawX();
- }
-
- @Override
- public float getRawY() {
- return mEvent.getRawY();
- }
-
- @Override
- public int getPointerCount() {
- return mEvent.getPointerCount();
- }
-
- @Override
- public boolean isTouchpadScroll() {
- // Touchpad inputs are treated as mouse inputs, and when scrolling, there are no buttons
- // returned.
- return isMouseEvent() && isActionMove() && mEvent.getButtonState() == 0;
- }
-
- @Override
- public boolean isOverDragHotspot() {
- return isOverItem() && getDocumentDetails().isInDragHotspot(this);
- }
-
- @Override
- public boolean isOverItem() {
- return getItemPosition() != RecyclerView.NO_POSITION;
- }
-
- @Override
- public boolean isOverDocIcon() {
- return isOverItem() && getDocumentDetails().isOverDocIcon(this);
- }
-
- @Override
- public boolean isOverModelItem() {
- return isOverItem() && getDocumentDetails().hasModelId();
- }
-
- @Override
- public int getItemPosition() {
- if (mPosition == UNSET_POSITION) {
- View child = mRecView.findChildViewUnder(mEvent.getX(), mEvent.getY());
- mPosition = (child != null)
- ? mRecView.getChildAdapterPosition(child)
- : RecyclerView.NO_POSITION;
- }
- return mPosition;
- }
-
- @Override
- public @Nullable DocumentDetails getDocumentDetails() {
- if (mDocDetails == null) {
- View childView = mRecView.findChildViewUnder(mEvent.getX(), mEvent.getY());
- mDocDetails = (childView != null)
- ? (DocumentHolder) mRecView.getChildViewHolder(childView)
- : null;
- }
- if (isOverItem()) {
- assert(mDocDetails != null);
- }
- return mDocDetails;
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("MotionInputEvent {")
- .append("isMouseEvent=").append(isMouseEvent())
- .append(" isPrimaryButtonPressed=").append(isPrimaryButtonPressed())
- .append(" isSecondaryButtonPressed=").append(isSecondaryButtonPressed())
- .append(" isShiftKeyDown=").append(isShiftKeyDown())
- .append(" isAltKeyDown=").append(isAltKeyDown())
- .append(" action(decoded)=").append(
- MotionEvent.actionToString(mEvent.getActionMasked()))
- .append(" getOrigin=").append(getOrigin())
- .append(" isOverItem=").append(isOverItem())
- .append(" getItemPosition=").append(getItemPosition())
- .append(" getDocumentDetails=").append(getDocumentDetails())
- .append(" getPointerCount=").append(getPointerCount())
- .append("}")
- .toString();
- }
+ public static boolean isMouseDragEvent(MotionEvent e) {
+ return isMouseEvent(e)
+ && isActionMove(e)
+ && isPrimaryButtonPressed(e);
}
}
diff --git a/src/com/android/documentsui/base/Features.java b/src/com/android/documentsui/base/Features.java
index 7a9936f..7714353 100644
--- a/src/com/android/documentsui/base/Features.java
+++ b/src/com/android/documentsui/base/Features.java
@@ -106,6 +106,10 @@
return isEnabled(R.bool.feature_content_refresh);
}
+ private boolean isFunPolicyEnabled() {
+ return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_FUN);
+ }
+
private boolean isDebugPolicyEnabled() {
return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
}
@@ -120,15 +124,12 @@
return isEnabled(R.bool.feature_folders_in_search_results);
}
- private boolean isFunPolicyEnabled() {
- return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_FUN);
- }
-
@Override
public boolean isGestureScaleEnabled() {
return isEnabled(R.bool.feature_gesture_scale);
}
+ @Override
public boolean isInspectorEnabled() {
return isEnabled(R.bool.feature_inspector);
}
diff --git a/src/com/android/documentsui/base/Lookup.java b/src/com/android/documentsui/base/Lookup.java
index 7057bfc..34253bb 100644
--- a/src/com/android/documentsui/base/Lookup.java
+++ b/src/com/android/documentsui/base/Lookup.java
@@ -21,8 +21,11 @@
/**
* A {@link Function}-like interface for looking up information.
+ *
+ * @param K input type (the "key").
+ * @param V output type (the "value").
*/
@FunctionalInterface
-public interface Lookup<T, R> {
- @Nullable R lookup(T key);
+public interface Lookup<K, V> {
+ @Nullable V lookup(K key);
}
diff --git a/src/com/android/documentsui/base/Shared.java b/src/com/android/documentsui/base/Shared.java
index d0ee2de..5d1cb90 100644
--- a/src/com/android/documentsui/base/Shared.java
+++ b/src/com/android/documentsui/base/Shared.java
@@ -34,13 +34,12 @@
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
+import android.view.View;
import android.view.WindowManager;
import com.android.documentsui.R;
import com.android.documentsui.ui.MessageBuilder;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
@@ -59,6 +58,12 @@
public static final String ACTION_PICK_COPY_DESTINATION =
"com.android.documentsui.PICK_COPY_DESTINATION";
+ // These values track values declared in MediaDocumentsProvider.
+ public static final String METADATA_KEY_AUDIO = "android.media.metadata.audio";
+ public static final String METADATA_KEY_VIDEO = "android.media.metadata.video";
+ public static final String METADATA_VIDEO_LATITUDE = "android.media.metadata.video:latitude";
+ public static final String METADATA_VIDEO_LONGITUTE = "android.media.metadata.video:longitude";
+
/**
* Extra boolean flag for {@link #ACTION_PICK_COPY_DESTINATION}, which
* specifies if the destination directory needs to create new directory or not.
@@ -261,12 +266,37 @@
}
}
+ /**
+ * This method exists solely to smooth over the fact that two different types of
+ * views cannot be bound to the same id in different layouts. "What's this crazy-pants
+ * stuff?", you say? Here's an example:
+ *
+ * The main DocumentsUI view (aka "Files app") when running on a phone has a drop-down
+ * "breadcrumb" (file path representation) in both landscape and portrait orientation.
+ * Larger format devices, like a tablet, use a horizontal "Dir1 > Dir2 > Dir3" format
+ * breadcrumb in landscape layouts, but the regular drop-down breadcrumb in portrait
+ * mode.
+ *
+ * Our initial inclination was to give each of those views the same ID (as they both
+ * implement the same "Breadcrumb" interface). But at runtime, when rotating a device
+ * from one orientation to the other, deeeeeeep within the UI toolkit a exception
+ * would happen, because one view instance (drop-down) was being inflated in place of
+ * another (horizontal). I'm writing this code comment significantly after the face,
+ * so I don't recall all of the details, but it had to do with View type-checking the
+ * Parcelable state in onRestore, or something like that. Either way, this isn't
+ * allowed (my patch to fix this was rejected).
+ *
+ * To work around this we have this cute little method that accepts multiple
+ * resource IDs, and along w/ type inference finds our view, no matter which
+ * id it is wearing, and returns it.
+ */
+ @SuppressWarnings("TypeParameterUnusedInFormals")
public static @Nullable <T> T findView(Activity activity, int... resources) {
for (int id : resources) {
@SuppressWarnings("unchecked")
- T r = (T) activity.findViewById(id);
- if (r != null) {
- return r;
+ View view = activity.findViewById(id);
+ if (view != null) {
+ return (T) view;
}
}
return null;
diff --git a/src/com/android/documentsui/base/State.java b/src/com/android/documentsui/base/State.java
index fbfd385..13a28ef 100644
--- a/src/com/android/documentsui/base/State.java
+++ b/src/com/android/documentsui/base/State.java
@@ -20,7 +20,6 @@
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
-import android.provider.DocumentsContract;
import android.util.SparseArray;
import com.android.documentsui.services.FileOperationService;
@@ -30,6 +29,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -139,7 +139,7 @@
public String toString() {
return "State{"
+ "action=" + action
- + ", acceptMimes=" + acceptMimes
+ + ", acceptMimes=" + Arrays.toString(acceptMimes)
+ ", allowMultiple=" + allowMultiple
+ ", localOnly=" + localOnly
+ ", showDeviceStorageOption=" + showDeviceStorageOption
diff --git a/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java b/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java
index 6bf0d8b..2af3850 100644
--- a/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java
+++ b/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java
@@ -21,10 +21,10 @@
import android.view.ViewGroup;
import com.android.documentsui.Model;
+import com.android.documentsui.Model.Update;
import com.android.documentsui.base.EventListener;
import com.android.documentsui.dirlist.Message.HeaderMessage;
import com.android.documentsui.dirlist.Message.InflateMessage;
-import com.android.documentsui.Model.Update;
import java.util.List;
@@ -238,8 +238,8 @@
}
@Override
- public List<String> getModelIds() {
- return mDelegate.getModelIds();
+ public List<String> getStableIds() {
+ return mDelegate.getStableIds();
}
@Override
@@ -248,7 +248,7 @@
}
@Override
- public String getModelId(int p) {
+ public String getStableId(int p) {
if (p == mBreakPosition) {
return null;
}
@@ -261,12 +261,12 @@
return null;
}
- return mDelegate.getModelId(toDelegatePosition(p));
+ return mDelegate.getStableId(toDelegatePosition(p));
}
@Override
- public void onItemSelectionChanged(String id) {
- mDelegate.onItemSelectionChanged(id);
+ public int getPosition(String id) {
+ return toViewPosition(mDelegate.getPosition(id));
}
// Listener we add to our delegate. This allows us to relay events published
diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 9096f63..9814bfc 100644
--- a/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -16,7 +16,6 @@
package com.android.documentsui.dirlist;
-import static com.android.documentsui.base.DocumentInfo.getCursorInt;
import static com.android.documentsui.base.DocumentInfo.getCursorString;
import static com.android.documentsui.base.Shared.DEBUG;
import static com.android.documentsui.base.Shared.VERBOSE;
@@ -41,6 +40,7 @@
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
+import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
@@ -50,7 +50,7 @@
import android.util.Log;
import android.util.SparseArray;
import android.view.ContextMenu;
-import android.view.HapticFeedbackConstants;
+import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -63,7 +63,6 @@
import com.android.documentsui.ActionModeController;
import com.android.documentsui.BaseActivity;
import com.android.documentsui.BaseActivity.RetainedState;
-import com.android.documentsui.DirectoryReloadLock;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.FocusManager;
import com.android.documentsui.Injector;
@@ -76,10 +75,7 @@
import com.android.documentsui.base.DocumentFilters;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
-import com.android.documentsui.base.EventHandler;
import com.android.documentsui.base.EventListener;
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.base.Events.MotionInputEvent;
import com.android.documentsui.base.Features;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
@@ -90,11 +86,20 @@
import com.android.documentsui.clipping.UrisSupplier;
import com.android.documentsui.dirlist.AnimationView.AnimationType;
import com.android.documentsui.picker.PickActivity;
-import com.android.documentsui.selection.BandController;
-import com.android.documentsui.selection.GestureSelector;
+import com.android.documentsui.selection.BandSelectionHelper;
+import com.android.documentsui.selection.ContentLock;
+import com.android.documentsui.selection.DefaultBandHost;
+import com.android.documentsui.selection.DefaultBandPredicate;
+import com.android.documentsui.selection.GestureRouter;
+import com.android.documentsui.selection.GestureSelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup;
+import com.android.documentsui.selection.MotionInputHandler;
+import com.android.documentsui.selection.MouseInputHandler;
import com.android.documentsui.selection.Selection;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.selection.SelectionMetadata;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+import com.android.documentsui.selection.TouchEventRouter;
+import com.android.documentsui.selection.TouchInputHandler;
import com.android.documentsui.services.FileOperation;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
@@ -107,8 +112,6 @@
import java.lang.annotation.RetentionPolicy;
import java.util.List;
-import javax.annotation.Nullable;
-
/**
* Display the documents inside a single directory.
*/
@@ -124,7 +127,7 @@
public @interface RequestCode {}
public static final int REQUEST_COPY_DESTINATION = 1;
- private static final String TAG = "DirectoryFragment";
+ static final String TAG = "DirectoryFragment";
private static final int LOADER_ID = 42;
private static final int CACHE_EVICT_LIMIT = 100;
@@ -143,7 +146,7 @@
@Injected
@ContentScoped
- private SelectionManager mSelectionMgr;
+ private SelectionHelper mSelectionMgr;
@Injected
@ContentScoped
@@ -157,14 +160,14 @@
@ContentScoped
private ActionModeController mActionModeController;
+ private ItemDetailsLookup mDetailsLookup;
private SelectionMetadata mSelectionMetadata;
- private UserInputHandler<InputEvent> mInputHandler;
- private @Nullable BandController mBandController;
+ private KeyInputHandler mKeyListener;
+ private @Nullable BandSelectionHelper mBandSelector;
private @Nullable DragHoverListener mDragHoverListener;
private IconHelper mIconHelper;
private SwipeRefreshLayout mRefreshLayout;
private RecyclerView mRecView;
-
private DocumentsAdapter mAdapter;
private DocumentClipper mClipper;
private GridLayoutManager mLayout;
@@ -176,9 +179,11 @@
private View mProgressBar;
private DirectoryState mLocalState;
- private DirectoryReloadLock mReloadLock = new DirectoryReloadLock();
- private Runnable mBandSelectStarted;
+ // Blocks loading/reloading of content while user is actively making selection.
+ private ContentLock mContentLock = new ContentLock();
+
+ private Runnable mBandSelectStartedCallback;
// Note, we use !null to indicate that selection was restored (from rotation).
// So don't fiddle with this field unless you've got the bigger picture in mind.
@@ -201,7 +206,7 @@
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
mProgressBar = view.findViewById(R.id.progressbar);
- assert(mProgressBar != null);
+ assert mProgressBar != null;
mRecView = (RecyclerView) view.findViewById(R.id.dir_list);
mRecView.setRecyclerListener(
@@ -261,8 +266,8 @@
mModel.removeUpdateListener(mModelUpdateListener);
mModel.removeUpdateListener(mAdapter.getModelUpdateListener());
- if (mBandController != null) {
- mBandController.removeBandSelectStartedListener(mBandSelectStarted);
+ if (mBandSelector != null) {
+ mBandSelector.removeOnBandStartedListener(mBandSelectStartedCallback);
}
super.onDestroyView();
@@ -316,77 +321,99 @@
mModel.addUpdateListener(mAdapter.getModelUpdateListener());
mModel.addUpdateListener(mModelUpdateListener);
- mSelectionMgr = mInjector.getSelectionManager(mAdapter, this::canSetSelectionState);
+ SelectionPredicate selectionPredicate =
+ new DocsSelectionPredicate(mInjector.config, mState, mModel, mRecView);
+
+ mSelectionMgr = mInjector.getSelectionManager(mAdapter, selectionPredicate);
mFocusManager = mInjector.getFocusManager(mRecView, mModel);
- mActions = mInjector.getActionHandler(mReloadLock);
+ mActions = mInjector.getActionHandler(mContentLock);
mRecView.setAccessibilityDelegateCompat(
new AccessibilityEventRouter(mRecView,
(View child) -> onAccessibilityClick(child)));
mSelectionMetadata = new SelectionMetadata(mModel::getItem);
- mSelectionMgr.addItemCallback(mSelectionMetadata);
+ mSelectionMgr.addObserver(mSelectionMetadata);
+ mDetailsLookup = new DocsItemDetailsLookup(mRecView);
- GestureSelector gestureSel = GestureSelector.create(mSelectionMgr, mRecView, mReloadLock);
+ GestureSelectionHelper gestureHelper =
+ GestureSelectionHelper.create(mSelectionMgr, mRecView, mContentLock);
if (mState.allowMultiple) {
- mBandController = new BandController(
- mRecView,
+ mBandSelector = new BandSelectionHelper(
+ new DefaultBandHost(mRecView, R.drawable.band_select_overlay),
mAdapter,
+ new DocsStableIdProvider(mAdapter),
mSelectionMgr,
- mReloadLock,
- (int pos) -> {
- // The band selection model only operates on documents and directories.
- // Exclude other types of adapter items like whitespace and dividers.
- RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(pos);
- return ModelBackedDocumentsAdapter.isContentType(vh.getItemViewType());
- });
- mBandSelectStarted = mFocusManager::clearFocus;
- mBandController.addBandSelectStartedListener(mBandSelectStarted);
+ selectionPredicate,
+ new DefaultBandPredicate(mDetailsLookup),
+ mContentLock);
+
+ mBandSelectStartedCallback = mFocusManager::clearFocus;
+ mBandSelector.addOnBandStartedListener(mBandSelectStartedCallback);
}
- DragStartListener mDragStartListener = mInjector.config.dragAndDropEnabled()
+ DragStartListener dragStartListener = mInjector.config.dragAndDropEnabled()
? DragStartListener.create(
mIconHelper,
mModel,
mSelectionMgr,
mSelectionMetadata,
mState,
+ mDetailsLookup,
this::getModelId,
mRecView::findChildViewUnder,
DocumentsApplication.getDragAndDropManager(mActivity))
: DragStartListener.DUMMY;
- EventHandler<InputEvent> gestureHandler = mState.allowMultiple
- ? gestureSel::start
- : EventHandler.createStub(false);
-
- mInputHandler = new UserInputHandler<>(
+ // Construction of the input handlers is non trivial, so to keep logic clear,
+ // and code flexible, and DirectoryFragment small, the construction has been
+ // moved off into a separate class.
+ InputHandlers handlers = new InputHandlers(
mActions,
- mFocusManager,
mSelectionMgr,
- (MotionEvent t) -> MotionInputEvent.obtain(t, mRecView),
- this::canSelect,
- this::onContextMenuClick,
- mDragStartListener::onTouchDragEvent,
- gestureHandler,
- () -> mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS));
-
- new ListeningGestureDetector(
- mInjector.features,
- this.getContext(),
+ selectionPredicate,
+ mDetailsLookup,
+ mFocusManager,
mRecView,
- mDragStartListener::onMouseDragEvent,
- mRefreshLayout::setEnabled,
- gestureSel,
- mInputHandler,
- mBandController,
- this::scaleLayout);
+ mState);
+
+ MouseInputHandler mouseHandler =
+ handlers.createMouseHandler(this::onContextMenuClick);
+
+ TouchInputHandler touchHandler =
+ handlers.createTouchHandler(gestureHelper, dragStartListener);
+
+ GestureRouter<MotionInputHandler> gestureRouter = new GestureRouter<>(touchHandler);
+ gestureRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mouseHandler);
+
+ // This little guy gets added to each Holder, so that we can be notified of key events
+ // on RecyclerView items.
+ mKeyListener = handlers.createKeyHandler();
+
+ if (Build.IS_DEBUGGABLE) {
+ new ScaleHelper(this.getContext(), mInjector.features, this::scaleLayout)
+ .attach(mRecView);
+ }
+
+ new RefreshHelper(mRefreshLayout::setEnabled)
+ .attach(mRecView);
+
+ GestureDetector gestureDetector = new GestureDetector(getContext(), gestureRouter);
+
+ TouchEventRouter eventRouter = new TouchEventRouter(gestureDetector, gestureHelper);
+
+ eventRouter.register(
+ MotionEvent.TOOL_TYPE_MOUSE,
+ new MouseDragEventInterceptor(
+ mDetailsLookup, dragStartListener::onMouseDragEvent, mBandSelector));
+
+ mRecView.addOnItemTouchListener(eventRouter);
mActionModeController = mInjector.getActionModeController(
mSelectionMetadata,
this::handleMenuItemClick);
- mSelectionMgr.addCallback(mActionModeController);
+ mSelectionMgr.addObserver(mActionModeController);
final ActivityManager am = (ActivityManager) mActivity.getSystemService(
Context.ACTIVITY_SERVICE);
@@ -428,7 +455,8 @@
}
public void retainState(RetainedState state) {
- state.selection = mSelectionMgr.getSelection(new Selection());
+ state.selection = new Selection();
+ mSelectionMgr.copySelection(state.selection);
}
@Override
@@ -452,7 +480,8 @@
// at the same time.
mInjector.menuManager.inflateContextMenuForContainer(menu, inflater);
} else {
- mInjector.menuManager.inflateContextMenuForDocs(menu, inflater, mSelectionMetadata);
+ mInjector.menuManager.inflateContextMenuForDocs(
+ menu, inflater, mSelectionMetadata);
}
}
@@ -482,23 +511,21 @@
jobId);
}
- protected boolean onContextMenuClick(InputEvent e) {
- final View v;
- final float x, y;
- if (e.isOverModelItem()) {
- DocumentHolder doc = (DocumentHolder) e.getDocumentDetails();
+ // TODO: Move to UserInputHander.
+ protected boolean onContextMenuClick(MotionEvent e) {
- v = doc.itemView;
- x = e.getX() - v.getLeft();
- y = e.getY() - v.getTop();
- } else {
- v = mRecView;
- x = e.getX();
- y = e.getY();
+ if (mDetailsLookup.overStableItem(e)) {
+ View childView = mRecView.findChildViewUnder(e.getX(), e.getY());
+ ViewHolder holder = mRecView.getChildViewHolder(childView);
+
+ View view = holder.itemView;
+ float x = e.getX() - view.getLeft();
+ float y = e.getY() - view.getTop();
+ mInjector.menuManager.showContextMenu(this, view, x, y);
+ return true;
}
- mInjector.menuManager.showContextMenu(this, v, x, y);
-
+ mInjector.menuManager.showContextMenu(this, mRecView, e.getX(), e.getY());
return true;
}
@@ -526,8 +553,8 @@
int pad = getDirectoryPadding(mode);
mRecView.setPadding(pad, pad, pad, pad);
mRecView.requestLayout();
- if (mBandController != null) {
- mBandController.handleLayoutChanged();
+ if (mBandSelector != null) {
+ mBandSelector.reset();
}
mIconHelper.setViewMode(mode);
}
@@ -537,7 +564,8 @@
* @param mode The new view mode.
*/
private void scaleLayout(float scale) {
- assert(Build.IS_DEBUGGABLE);
+ assert Build.IS_DEBUGGABLE;
+
if (VERBOSE) Log.v(
TAG, "Handling scale event: " + scale + ", existing scale: " + mLiveScale);
@@ -606,7 +634,8 @@
}
private boolean handleMenuItemClick(MenuItem item) {
- Selection selection = mSelectionMgr.getSelection(new Selection());
+ Selection selection = new Selection();
+ mSelectionMgr.copySelection(selection);
switch (item.getItemId()) {
case R.id.action_menu_open:
@@ -669,11 +698,15 @@
transferDocuments(selection, null, FileOperationService.OPERATION_MOVE);
return true;
- case R.id.action_menu_inspector:
+ case R.id.action_menu_inspect:
+ case R.id.dir_menu_inspect:
mActionModeController.finishActionMode();
- assert(selection.size() == 1);
- DocumentInfo doc = mModel.getDocuments(selection).get(0);
- mActions.showInspector(doc);
+ assert selection.size() <= 1;
+ DocumentInfo doc = selection.isEmpty()
+ ? mActivity.getCurrentDirectory()
+ : mModel.getDocuments(selection).get(0);
+
+ mActions.showInspector(doc);
return true;
case R.id.dir_menu_cut_to_clipboard:
@@ -720,8 +753,8 @@
}
private boolean onAccessibilityClick(View child) {
- DocumentDetails doc = getDocumentHolder(child);
- mActions.openDocument(doc, ActionHandler.VIEW_TYPE_PREVIEW,
+ DocumentHolder holder = getDocumentHolder(child);
+ mActions.openItem(holder.getItemDetails(), ActionHandler.VIEW_TYPE_PREVIEW,
ActionHandler.VIEW_TYPE_REGULAR);
return true;
}
@@ -749,7 +782,7 @@
private void showChooserForDoc(final Selection selected) {
Metrics.logUserAction(getContext(), Metrics.USER_ACTION_OPEN);
- assert(selected.size() == 1);
+ assert selected.size() == 1;
DocumentInfo doc =
DocumentInfo.fromDirectoryCursor(mModel.getItem(selected.iterator().next()));
mActions.showChooserForDoc(doc);
@@ -780,7 +813,7 @@
throw new RuntimeException("Failed to create uri supplier.", e);
}
- final DocumentInfo parent = mState.stack.peek();
+ final DocumentInfo parent = mActivity.getCurrentDirectory();
final FileOperation operation = new FileOperation.Builder()
.withOpType(mode)
.withSrcParent(parent == null ? null : parent.derivedUri)
@@ -871,7 +904,7 @@
// Batch renaming not supported
// Rename option is only available in menu when 1 document selected
- assert(selected.size() == 1);
+ assert selected.size() == 1;
// Model must be accessed in UI thread, since underlying cursor is not threadsafe.
List<DocumentInfo> docs = mModel.getDocuments(selected);
@@ -882,10 +915,6 @@
return mModel;
}
- private boolean isDocumentEnabled(String mimeType, int flags) {
- return mInjector.config.isDocumentEnabled(mimeType, flags, mState);
- }
-
/**
* Paste selection files from the primary clip into the current window.
*/
@@ -937,7 +966,7 @@
}
if (v == mRecView) {
- return mState.stack.peek();
+ return mActivity.getCurrentDirectory();
}
return null;
@@ -968,31 +997,6 @@
return null;
}
- // TODO: Move to activities when Model becomes activity level object.
- private boolean canSelect(DocumentDetails doc) {
- return canSetSelectionState(doc.getModelId(), true);
- }
-
- // TODO: Move to activities when Model becomes activity level object.
- private boolean canSetSelectionState(String modelId, boolean nextState) {
- if (nextState) {
- // Check if an item can be selected
- final Cursor cursor = mModel.getItem(modelId);
- if (cursor == null) {
- Log.w(TAG, "Couldn't obtain cursor for modelId: " + modelId);
- return false;
- }
-
- final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
- final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
- return mInjector.config.canSelectType(docMimeType, docFlags, mState);
- } else {
- final DocumentInfo parent = mState.stack.peek();
- // Right now all selected items can be deselected.
- return true;
- }
- }
-
public static void showDirectory(
FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
if (DEBUG) Log.d(TAG, "Showing directory: " + DocumentInfo.debugString(doc));
@@ -1056,7 +1060,7 @@
cache.removeUri(mModel.getItemUri(ids[i]));
}
- final DocumentInfo doc = mState.stack.peek();
+ final DocumentInfo doc = mActivity.getCurrentDirectory();
mActions.refreshDocument(doc, (boolean refreshSupported) -> {
if (refreshSupported) {
mRefreshLayout.setRefreshing(false);
@@ -1151,7 +1155,7 @@
@Override
public boolean isSelected(String id) {
- return mSelectionMgr.getSelection().contains(id);
+ return mSelectionMgr.isSelected(id);
}
@Override
@@ -1161,7 +1165,7 @@
@Override
public void initDocumentHolder(DocumentHolder holder) {
- holder.addKeyEventListener(mInputHandler);
+ holder.addKeyEventListener(mKeyListener);
holder.itemView.setOnFocusChangeListener(mFocusManager);
}
diff --git a/src/com/android/documentsui/dirlist/DocsItemDetailsLookup.java b/src/com/android/documentsui/dirlist/DocsItemDetailsLookup.java
new file mode 100644
index 0000000..78c3097
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/DocsItemDetailsLookup.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.documentsui.selection.ItemDetailsLookup;
+
+/**
+ * Access to details of an item associated with a {@link MotionEvent} instance.
+ */
+final class DocsItemDetailsLookup extends ItemDetailsLookup {
+
+ private final RecyclerView mRecView;
+
+ public DocsItemDetailsLookup(RecyclerView view) {
+ mRecView = view;
+ }
+
+ @Override
+ public boolean overItem(MotionEvent e) {
+ return getItemPosition(e) != RecyclerView.NO_POSITION;
+ }
+
+ @Override
+ public boolean overStableItem(MotionEvent e) {
+ return overItem(e) && getItemDetails(e).hasStableId();
+ }
+
+ @Override
+ public boolean inItemDragRegion(MotionEvent e) {
+ return overItem(e) && getItemDetails(e).inDragRegion(e);
+ }
+
+ @Override
+ public boolean inItemSelectRegion(MotionEvent e) {
+ return overItem(e) && getItemDetails(e).inSelectionHotspot(e);
+ }
+
+ @Override
+ public int getItemPosition(MotionEvent e) {
+ View child = mRecView.findChildViewUnder(e.getX(), e.getY());
+ return (child != null)
+ ? mRecView.getChildAdapterPosition(child)
+ : RecyclerView.NO_POSITION;
+ }
+
+ @Override
+ public ItemDetails getItemDetails(MotionEvent e) {
+ @Nullable DocumentHolder holder = getDocumentHolder(e);
+ return holder == null ? null : holder.getItemDetails();
+ }
+
+ private @Nullable DocumentHolder getDocumentHolder(MotionEvent e) {
+ View childView = mRecView.findChildViewUnder(e.getX(), e.getY());
+ if (childView != null) {
+ ViewHolder holder = mRecView.getChildViewHolder(childView);
+ if (holder instanceof DocumentHolder) {
+ return (DocumentHolder) holder;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/documentsui/dirlist/DocsSelectionPredicate.java b/src/com/android/documentsui/dirlist/DocsSelectionPredicate.java
new file mode 100644
index 0000000..679bd9f
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/DocsSelectionPredicate.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+import static com.android.documentsui.base.DocumentInfo.getCursorInt;
+import static com.android.documentsui.base.DocumentInfo.getCursorString;
+
+import android.database.Cursor;
+import android.provider.DocumentsContract.Document;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+
+import com.android.documentsui.ActivityConfig;
+import com.android.documentsui.Model;
+import com.android.documentsui.base.State;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+/**
+ * Class embodying the logic as to whether an item (specified by id or position)
+ * can be selected (or not).
+ */
+final class DocsSelectionPredicate extends SelectionPredicate {
+
+ private ActivityConfig mConfig;
+ private Model mModel;
+ private RecyclerView mRecView;
+ private State mState;
+
+ DocsSelectionPredicate(
+ ActivityConfig config, State state, Model model, RecyclerView recView) {
+
+ checkArgument(config != null);
+ checkArgument(state != null);
+ checkArgument(model != null);
+ checkArgument(recView != null);
+
+ mConfig = config;
+ mState = state;
+ mModel = model;
+ mRecView = recView;
+
+ }
+
+ @Override
+ public boolean canSetStateForId(String id, boolean nextState) {
+ if (nextState) {
+ // Check if an item can be selected
+ final Cursor cursor = mModel.getItem(id);
+ if (cursor == null) {
+ Log.w(DirectoryFragment.TAG, "Couldn't obtain cursor for id: " + id);
+ return false;
+ }
+
+ final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+ final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+ return mConfig.canSelectType(docMimeType, docFlags, mState);
+ }
+
+ // Right now all selected items can be deselected.
+ return true;
+ }
+
+ @Override
+ public boolean canSetStateAtPosition(int position, boolean nextState) {
+ // This method features a nextState arg for symmetry.
+ // But, there are no current uses for checking un-selecting state by position.
+ // So rather than have some unsuspecting client think canSetState(int, false)
+ // will ever do anything. Let's just be grumpy about it.
+ assert nextState == true;
+
+ // NOTE: Given that we have logic in some places disallowing selection,
+ // it may be a bug that Band and Gesture based selections don't
+ // also verify something can be unselected.
+
+ // The band selection model only operates on documents and directories.
+ // Exclude other types of adapter items like whitespace and dividers.
+ RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(position);
+ return ModelBackedDocumentsAdapter.isContentType(vh.getItemViewType());
+ }
+
+ @Override
+ public boolean canSelectMultiple() {
+ return mState.allowMultiple;
+ }
+}
diff --git a/src/com/android/documentsui/dirlist/DocsStableIdProvider.java b/src/com/android/documentsui/dirlist/DocsStableIdProvider.java
new file mode 100644
index 0000000..889b82a
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/DocsStableIdProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import com.android.documentsui.selection.SelectionHelper.StableIdProvider;
+
+import java.util.List;
+
+/**
+ * Provides RecyclerView selection code access to stable ids backed
+ * by DocumentsAdapter.
+ */
+public final class DocsStableIdProvider extends StableIdProvider {
+
+ private final DocumentsAdapter mAdapter;
+
+ public DocsStableIdProvider(DocumentsAdapter adapter) {
+ checkArgument(adapter != null);
+ mAdapter = adapter;
+ }
+
+ @Override
+ public String getStableId(int position) {
+ return mAdapter.getStableId(position);
+ }
+
+ @Override
+ public int getPosition(String id) {
+ return mAdapter.getPosition(id);
+ }
+
+ @Override
+ public List<String> getStableIds() {
+ return mAdapter.getStableIds();
+ }
+}
diff --git a/src/com/android/documentsui/dirlist/DocumentDetails.java b/src/com/android/documentsui/dirlist/DocumentDetails.java
deleted file mode 100644
index a321e64..0000000
--- a/src/com/android/documentsui/dirlist/DocumentDetails.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.dirlist;
-
-import com.android.documentsui.base.Events.InputEvent;
-
-/**
- * Interface providing a loose coupling between DocumentHolder.
- */
-public interface DocumentDetails {
- boolean hasModelId();
- String getModelId();
- int getAdapterPosition();
- boolean isInSelectionHotspot(InputEvent event);
- boolean isInDragHotspot(InputEvent event);
-
- /**
- * Given a mouse input event, this method does a hit-test to see if the cursor
- * is currently positioned over the document icon or checkbox in the case where
- * the document is selected.
- */
- boolean isOverDocIcon(InputEvent event);
-}
diff --git a/src/com/android/documentsui/dirlist/DocumentHolder.java b/src/com/android/documentsui/dirlist/DocumentHolder.java
index d7f7ce5..e1345f2 100644
--- a/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -16,33 +16,24 @@
package com.android.documentsui.dirlist;
-import android.annotation.ColorInt;
import android.content.Context;
import android.database.Cursor;
-import android.graphics.Rect;
-import android.os.Build;
import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
-import android.widget.FrameLayout;
import android.widget.ImageView;
-import com.android.documentsui.R;
-import com.android.documentsui.base.DebugFlags;
-import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.base.Shared;
-import com.android.documentsui.ui.DocumentDebugInfo;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
import javax.annotation.Nullable;
public abstract class DocumentHolder
- extends RecyclerView.ViewHolder
- implements View.OnKeyListener, DocumentDetails {
+ extends RecyclerView.ViewHolder implements View.OnKeyListener {
static final float DISABLED_ALPHA = 0.3f;
@@ -50,12 +41,11 @@
protected @Nullable String mModelId;
- private final View mSelectionHotspot;
- private @Nullable DocumentDebugInfo mDebugInfo;
-
// See #addKeyEventListener for details on the need for this field.
private KeyboardEventListener mKeyEventListener;
+ private final DocumentItemDetails mDetails;
+
public DocumentHolder(Context context, ViewGroup parent, int layout) {
this(context, inflateLayout(context, parent, layout));
}
@@ -66,8 +56,7 @@
itemView.setOnKeyListener(this);
mContext = context;
-
- mSelectionHotspot = itemView.findViewById(R.id.icon_check);
+ mDetails = new DocumentItemDetails();
}
/**
@@ -78,12 +67,6 @@
*/
public abstract void bind(Cursor cursor, String modelId);
- @Override
- public boolean hasModelId() {
- return !TextUtils.isEmpty(mModelId);
- }
-
- @Override
public String getModelId() {
return mModelId;
}
@@ -111,7 +94,7 @@
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
assert(mKeyEventListener != null);
- return mKeyEventListener.onKey(this, keyCode, event);
+ return mKeyEventListener.onKey(getItemDetails(), keyCode, event);
}
/**
@@ -127,28 +110,18 @@
mKeyEventListener = listener;
}
- @Override
- public boolean isInSelectionHotspot(InputEvent event) {
- // Do everything in global coordinates - it makes things simpler.
- int[] coords = new int[2];
- mSelectionHotspot.getLocationOnScreen(coords);
- Rect rect = new Rect(coords[0], coords[1], coords[0] + mSelectionHotspot.getWidth(),
- coords[1] + mSelectionHotspot.getHeight());
-
- // If the tap occurred within the icon rect, consider it a selection.
- return rect.contains((int) event.getRawX(), (int) event.getRawY());
- }
-
- @Override
- public boolean isInDragHotspot(InputEvent event) {
+ public boolean inDragRegion(MotionEvent event) {
return false;
}
- @Override
- public boolean isOverDocIcon(InputEvent event) {
+ public boolean inSelectRegion(MotionEvent event) {
return false;
}
+ public ItemDetails getItemDetails() {
+ return mDetails;
+ }
+
static void setEnabledRecursive(View itemView, boolean enabled) {
if (itemView == null || itemView.isEnabled() == enabled) {
return;
@@ -163,6 +136,7 @@
}
}
+ @SuppressWarnings("TypeParameterUnusedInFormals")
private static <V extends View> V inflateLayout(Context context, ViewGroup parent, int layout) {
final LayoutInflater inflater = LayoutInflater.from(context);
return (V) inflater.inflate(layout, parent, false);
@@ -172,20 +146,31 @@
return view.animate().setDuration(Shared.CHECK_ANIMATION_DURATION).alpha(alpha);
}
- /**
- * Implement this in order to be able to respond to events coming from DocumentHolders.
- * TODO: Make this bubble up logic events rather than having imperative commands.
- */
- interface KeyboardEventListener {
+ private final class DocumentItemDetails extends ItemDetails {
- /**
- * Handles key events on the document holder.
- *
- * @param doc The target DocumentHolder.
- * @param keyCode Key code for the event.
- * @param event KeyEvent for the event.
- * @return Whether the event was handled.
- */
- public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event);
+ @Override
+ public int getPosition() {
+ return DocumentHolder.this.getAdapterPosition();
+ }
+
+ @Override
+ public String getStableId() {
+ return DocumentHolder.this.getModelId();
+ }
+
+ @Override
+ public int getItemViewType() {
+ return DocumentHolder.this.getItemViewType();
+ }
+
+ @Override
+ public boolean inDragRegion(MotionEvent e) {
+ return DocumentHolder.this.inDragRegion(e);
+ }
+
+ @Override
+ public boolean inSelectionHotspot(MotionEvent e) {
+ return DocumentHolder.this.inSelectRegion(e);
+ }
}
}
diff --git a/src/com/android/documentsui/dirlist/DocumentsAdapter.java b/src/com/android/documentsui/dirlist/DocumentsAdapter.java
index 82f2524..f940814 100644
--- a/src/com/android/documentsui/dirlist/DocumentsAdapter.java
+++ b/src/com/android/documentsui/dirlist/DocumentsAdapter.java
@@ -33,7 +33,7 @@
import java.util.List;
/**
- * DocumentsAdapter provides glue between a directory Model, and RecylcerView. We've
+ * DocumentsAdapter provides glue between a directory Model, and RecyclerView. We've
* abstracted this a bit in order to decompose some specialized support
* for adding dummy layout objects (@see SectionBreakDocumentsAdapter). Handling of the
* dummy layout objects was error prone when interspersed with the core mode / adapter code.
@@ -41,8 +41,7 @@
* @see ModelBackedDocumentsAdapter
* @see DirectoryAddonsAdapter
*/
-public abstract class DocumentsAdapter
- extends RecyclerView.Adapter<DocumentHolder> {
+public abstract class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> {
// Item types used by ModelBackedDocumentsAdapter
public static final int ITEM_TYPE_DOCUMENT = 1;
public static final int ITEM_TYPE_DIRECTORY = 2;
@@ -51,28 +50,10 @@
public static final int ITEM_TYPE_HEADER_MESSAGE = Integer.MAX_VALUE - 1;
public static final int ITEM_TYPE_INFLATED_MESSAGE = Integer.MAX_VALUE - 2;
- // Payloads for notifyItemChange to distinguish between selection and other events.
- static final String SELECTION_CHANGED_MARKER = "Selection-Changed";
-
- /**
- * Returns a list of model IDs of items currently in the adapter.
- *
- * @return A list of Model IDs.
- */
- public abstract List<String> getModelIds();
-
public abstract int getAdapterPosition(String modelId);
-
- /**
- * Triggers item-change notifications by stable ID (as opposed to position).
- * Passing an unrecognized ID will result in a warning in logcat, but no other error.
- */
- public abstract void onItemSelectionChanged(String id);
-
- /**
- * @return The model ID of the item at the given adapter position.
- */
- public abstract String getModelId(int position);
+ public abstract String getStableId(int adapterPosition);
+ public abstract List<String> getStableIds();
+ public abstract int getPosition(String id);
abstract EventListener<Model.Update> getModelUpdateListener();
@@ -85,17 +66,13 @@
throw new UnsupportedOperationException();
}
- public boolean hasModelIds() {
- return !getModelIds().isEmpty();
- }
-
static boolean isDirectory(Cursor cursor) {
final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
return Document.MIME_TYPE_DIR.equals(mimeType);
}
boolean isDirectory(Model model, int position) {
- String modelId = getModelIds().get(position);
+ String modelId = getStableIds().get(position);
Cursor cursor = model.getItem(modelId);
return isDirectory(cursor);
}
diff --git a/src/com/android/documentsui/dirlist/DragHost.java b/src/com/android/documentsui/dirlist/DragHost.java
index 987303a..787431c 100644
--- a/src/com/android/documentsui/dirlist/DragHost.java
+++ b/src/com/android/documentsui/dirlist/DragHost.java
@@ -32,7 +32,7 @@
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.State;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.ui.DialogController;
import java.util.function.Predicate;
@@ -45,7 +45,7 @@
private static final String TAG = "dirlist.DragHost";
private final T mActivity;
- private final SelectionManager mSelectionMgr;
+ private final SelectionHelper mSelectionMgr;
private final ActionHandler mActions;
private final State mState;
private final DialogController mDialogs;
@@ -56,7 +56,7 @@
DragHost(
T activity,
DragAndDropManager dragAndDropManager,
- SelectionManager selectionMgr,
+ SelectionHelper selectionMgr,
ActionHandler actions,
State state,
DialogController dialogs,
diff --git a/src/com/android/documentsui/dirlist/DragHoverListener.java b/src/com/android/documentsui/dirlist/DragHoverListener.java
index 63d93ec..7babe26 100644
--- a/src/com/android/documentsui/dirlist/DragHoverListener.java
+++ b/src/com/android/documentsui/dirlist/DragHoverListener.java
@@ -24,9 +24,9 @@
import com.android.documentsui.ItemDragListener;
import com.android.documentsui.ItemDragListener.DragHost;
-import com.android.documentsui.ui.ViewAutoScroller;
-import com.android.documentsui.ui.ViewAutoScroller.ScrollActionDelegate;
-import com.android.documentsui.ui.ViewAutoScroller.ScrollDistanceDelegate;
+import com.android.documentsui.selection.ViewAutoScroller;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollHost;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollerCallbacks;
import java.util.function.BooleanSupplier;
import java.util.function.IntSupplier;
@@ -66,14 +66,15 @@
Predicate<View> isScrollView,
BooleanSupplier scrollUpSupplier,
BooleanSupplier scrollDownSupplier,
- ViewAutoScroller.ScrollActionDelegate actionDelegate) {
+ ViewAutoScroller.ScrollerCallbacks scrollCallbacks) {
+
mDragHandler = dragHandler;
mHeight = heightSupplier;
mIsScrollView = isScrollView;
mCanScrollUp = scrollUpSupplier;
mCanScrollDown = scrollDownSupplier;
- ScrollDistanceDelegate distanceDelegate = new ScrollDistanceDelegate() {
+ ScrollHost scrollHost = new ScrollHost() {
@Override
public Point getCurrentPosition() {
return mCurrentPosition;
@@ -90,13 +91,14 @@
}
};
- mDragScroller = new ViewAutoScroller(distanceDelegate, actionDelegate);
+ mDragScroller = new ViewAutoScroller(scrollHost, scrollCallbacks);
}
static DragHoverListener create(
ItemDragListener<? extends DragHost> dragHandler,
View scrollView) {
- ScrollActionDelegate actionDelegate = new ScrollActionDelegate() {
+
+ ScrollerCallbacks scrollCallbacks = new ScrollerCallbacks() {
@Override
public void scrollBy(int dy) {
scrollView.scrollBy(0, dy);
@@ -113,13 +115,15 @@
scrollView.removeCallbacks(r);
}
};
+
DragHoverListener listener = new DragHoverListener(
dragHandler,
scrollView::getHeight,
(view) -> (scrollView == view),
() -> scrollView.canScrollVertically(-1),
() -> scrollView.canScrollVertically(1),
- actionDelegate);
+ scrollCallbacks);
+
return listener;
}
diff --git a/src/com/android/documentsui/dirlist/DragStartListener.java b/src/com/android/documentsui/dirlist/DragStartListener.java
index 1651603..9d03925 100644
--- a/src/com/android/documentsui/dirlist/DragStartListener.java
+++ b/src/com/android/documentsui/dirlist/DragStartListener.java
@@ -17,10 +17,12 @@
package com.android.documentsui.dirlist;
import static com.android.documentsui.base.Shared.DEBUG;
+import static com.android.internal.util.Preconditions.checkArgument;
import android.net.Uri;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
+import android.view.MotionEvent;
import android.view.View;
import com.android.documentsui.DragAndDropManager;
@@ -28,10 +30,11 @@
import com.android.documentsui.Model;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.Events;
-import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.base.State;
+import com.android.documentsui.selection.ItemDetailsLookup;
+import com.android.documentsui.selection.MutableSelection;
import com.android.documentsui.selection.Selection;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.SelectionHelper;
import java.util.ArrayList;
import java.util.List;
@@ -42,44 +45,47 @@
/**
* Listens for potential "drag-like" events and kick-start dragging as needed. Also allows external
* direct call to {@code #startDrag(RecyclerView, View)} if explicit start is needed, such as long-
- * pressing on an item via touch. (e.g. {@link UserInputHandler#onLongPress(InputEvent)} via touch.)
+ * pressing on an item via touch. (e.g. InputEventDispatcher#onLongPress(MotionEvent)} via touch.
*/
interface DragStartListener {
static final DragStartListener DUMMY = new DragStartListener() {
@Override
- public boolean onMouseDragEvent(InputEvent event) {
+ public boolean onMouseDragEvent(MotionEvent event) {
return false;
}
@Override
- public boolean onTouchDragEvent(InputEvent event) {
+ public boolean onTouchDragEvent(MotionEvent event) {
return false;
}
};
- boolean onMouseDragEvent(InputEvent event);
- boolean onTouchDragEvent(InputEvent event);
+ boolean onMouseDragEvent(MotionEvent event);
+ boolean onTouchDragEvent(MotionEvent event);
@VisibleForTesting
- class ActiveListener implements DragStartListener {
+ class RuntimeDragStartListener implements DragStartListener {
private static String TAG = "DragStartListener";
private final IconHelper mIconHelper;
private final State mState;
- private final SelectionManager mSelectionMgr;
+ private final ItemDetailsLookup mDetailsLookup;
+ private final SelectionHelper mSelectionMgr;
private final SelectionDetails mSelectionDetails;
private final ViewFinder mViewFinder;
private final Function<View, String> mIdFinder;
private final Function<Selection, List<DocumentInfo>> mDocsConverter;
private final DragAndDropManager mDragAndDropManager;
+
// use DragStartListener.create
@VisibleForTesting
- public ActiveListener(
+ public RuntimeDragStartListener(
IconHelper iconHelper,
State state,
- SelectionManager selectionMgr,
+ ItemDetailsLookup detailsLookup,
+ SelectionHelper selectionMgr,
SelectionDetails selectionDetails,
ViewFinder viewFinder,
Function<View, String> idFinder,
@@ -88,6 +94,7 @@
mIconHelper = iconHelper;
mState = state;
+ mDetailsLookup = detailsLookup;
mSelectionMgr = selectionMgr;
mSelectionDetails = selectionDetails;
mViewFinder = viewFinder;
@@ -97,20 +104,22 @@
}
@Override
- public final boolean onMouseDragEvent(InputEvent event) {
- assert(Events.isMouseDragEvent(event));
+ public final boolean onMouseDragEvent(MotionEvent event) {
+ checkArgument(Events.isMouseDragEvent(event));
+ checkArgument(mDetailsLookup.inItemDragRegion(event));
+
return startDrag(mViewFinder.findView(event.getX(), event.getY()), event);
}
@Override
- public final boolean onTouchDragEvent(InputEvent event) {
+ public final boolean onTouchDragEvent(MotionEvent event) {
return startDrag(mViewFinder.findView(event.getX(), event.getY()), event);
}
/**
* May be called externally when drag is initiated from other event handling code.
*/
- private boolean startDrag(@Nullable View view, InputEvent event) {
+ private boolean startDrag(@Nullable View view, MotionEvent event) {
if (view == null) {
if (DEBUG) Log.d(TAG, "Ignoring drag event, null view.");
@@ -145,21 +154,22 @@
}
/**
- * Given the InputEvent (for CTRL case) and modelId of the view associated with the
+ * Given the MotionEvent (for CTRL case) and modelId of the view associated with the
* coordinates of the event, return a valid selection for drag and drop operation
*/
@VisibleForTesting
- Selection getSelectionToBeCopied(String modelId, InputEvent event) {
- Selection selection = new Selection();
+ MutableSelection getSelectionToBeCopied(String modelId, MotionEvent event) {
+ MutableSelection selection = new MutableSelection();
// If CTRL-key is held down and there's other existing selection, add item to
// selection (if not already selected)
- if (event.isCtrlKeyDown() && !mSelectionMgr.getSelection().contains(modelId)
- && mSelectionMgr.hasSelection()) {
- mSelectionMgr.toggleSelection(modelId);
+ if (Events.isCtrlKeyPressed(event)
+ && mSelectionMgr.hasSelection()
+ && !mSelectionMgr.isSelected(modelId)) {
+ mSelectionMgr.select(modelId);
}
- if (mSelectionMgr.getSelection().contains(modelId)) {
- mSelectionMgr.getSelection(selection);
+ if (mSelectionMgr.isSelected(modelId)) {
+ mSelectionMgr.copySelection(selection);
} else {
selection.add(modelId);
mSelectionMgr.clearSelection();
@@ -171,16 +181,18 @@
static DragStartListener create(
IconHelper iconHelper,
Model model,
- SelectionManager selectionMgr,
+ SelectionHelper selectionMgr,
SelectionDetails selectionDetails,
State state,
+ ItemDetailsLookup detailsLookup,
Function<View, String> idFinder,
ViewFinder viewFinder,
DragAndDropManager dragAndDropManager) {
- return new ActiveListener(
+ return new RuntimeDragStartListener(
iconHelper,
state,
+ detailsLookup,
selectionMgr,
selectionDetails,
viewFinder,
diff --git a/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
index cf793db..5d02957 100644
--- a/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
+++ b/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
@@ -22,15 +22,12 @@
import android.database.Cursor;
import android.graphics.Rect;
import android.provider.DocumentsContract.Document;
+import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.documentsui.R;
-import com.android.documentsui.base.DebugFlags;
-import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.roots.RootCursorWrapper;
final class GridDirectoryHolder extends DocumentHolder {
@@ -62,13 +59,13 @@
}
@Override
- public boolean isInDragHotspot(InputEvent event) {
+ public boolean inDragRegion(MotionEvent event) {
// Entire grid box should be draggable
return true;
}
@Override
- public boolean isOverDocIcon(InputEvent event) {
+ public boolean inSelectRegion(MotionEvent event) {
Rect iconRect = new Rect();
mIconMime.getGlobalVisibleRect(iconRect);
diff --git a/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index e96d09f..95be1b9 100644
--- a/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -25,15 +25,14 @@
import android.graphics.Rect;
import android.provider.DocumentsContract.Document;
import android.text.format.Formatter;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.documentsui.R;
-import com.android.documentsui.base.DebugFlags;
import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.base.Shared;
import com.android.documentsui.roots.RootCursorWrapper;
@@ -112,13 +111,13 @@
}
@Override
- public boolean isInDragHotspot(InputEvent event) {
+ public boolean inDragRegion(MotionEvent event) {
// Entire grid box should be draggable
return true;
}
@Override
- public boolean isOverDocIcon(InputEvent event) {
+ public boolean inSelectRegion(MotionEvent event) {
Rect iconRect = new Rect();
mIconMimeSm.getGlobalVisibleRect(iconRect);
diff --git a/src/com/android/documentsui/dirlist/InputHandlers.java b/src/com/android/documentsui/dirlist/InputHandlers.java
new file mode 100644
index 0000000..43143d4
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/InputHandlers.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import com.android.documentsui.ActionHandler;
+import com.android.documentsui.base.EventHandler;
+import com.android.documentsui.base.State;
+import com.android.documentsui.selection.GestureSelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup;
+import com.android.documentsui.selection.MouseInputHandler;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.TouchInputHandler;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+/**
+ * Helper class dedicated to building gesture input handlers. The construction
+ * of the various input handlers is non trivial. To keep logic clear,
+ * code flexible, and DirectoryFragment small(er), the construction has been
+ * isolated here in a separate class.
+ */
+final class InputHandlers {
+
+ private ActionHandler mActions;
+ private SelectionHelper mSelectionHelper;
+ private SelectionPredicate mSelectionPredicate;
+ private ItemDetailsLookup mDetailsLookup;
+ private FocusHandler mFocusHandler;
+ private RecyclerView mRecView;
+ private State mState;
+
+ InputHandlers(
+ ActionHandler actions,
+ SelectionHelper selectionHelper,
+ SelectionPredicate selectionPredicate,
+ ItemDetailsLookup detailsLookup,
+ FocusHandler focusHandler,
+ RecyclerView recView,
+ State state) {
+
+ checkArgument(actions != null);
+ checkArgument(selectionHelper != null);
+ checkArgument(selectionPredicate != null);
+ checkArgument(detailsLookup != null);
+ checkArgument(focusHandler != null);
+ checkArgument(recView != null);
+ checkArgument(state != null);
+
+ mActions = actions;
+ mSelectionHelper = selectionHelper;
+ mSelectionPredicate = selectionPredicate;
+ mDetailsLookup = detailsLookup;
+ mFocusHandler = focusHandler;
+ mRecView = recView;
+ mState = state;
+ }
+
+ KeyInputHandler createKeyHandler() {
+ KeyInputHandler.Callbacks callbacks = new KeyInputHandler.Callbacks() {
+ @Override
+ public boolean isInteractiveItem(ItemDetails item, KeyEvent e) {
+ switch (item.getItemViewType()) {
+ case DocumentsAdapter.ITEM_TYPE_HEADER_MESSAGE:
+ case DocumentsAdapter.ITEM_TYPE_INFLATED_MESSAGE:
+ case DocumentsAdapter.ITEM_TYPE_SECTION_BREAK:
+ return false;
+ case DocumentsAdapter.ITEM_TYPE_DOCUMENT:
+ case DocumentsAdapter.ITEM_TYPE_DIRECTORY:
+ return true;
+ default:
+ throw new RuntimeException(
+ "Unsupported item type: " + item.getItemViewType());
+ }
+ }
+
+ @Override
+ public boolean onItemActivated(ItemDetails item, KeyEvent e) {
+ // Handle enter key events
+ switch (e.getKeyCode()) {
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_BUTTON_A:
+ return mActions.openItem(
+ item,
+ ActionHandler.VIEW_TYPE_REGULAR,
+ ActionHandler.VIEW_TYPE_PREVIEW);
+ case KeyEvent.KEYCODE_SPACE:
+ return mActions.openItem(
+ item,
+ ActionHandler.VIEW_TYPE_PREVIEW,
+ ActionHandler.VIEW_TYPE_NONE);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onFocusItem(ItemDetails details, int keyCode, KeyEvent event) {
+ ViewHolder holder =
+ mRecView.findViewHolderForAdapterPosition(details.getPosition());
+ if (holder instanceof DocumentHolder) {
+ return mFocusHandler.handleKey((DocumentHolder) holder, keyCode, event);
+ }
+ return false;
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+ };
+
+ return new KeyInputHandler(mSelectionHelper, mSelectionPredicate, callbacks);
+ }
+
+ MouseInputHandler createMouseHandler(
+ EventHandler<MotionEvent> showContextMenuCallback) {
+
+ checkArgument(showContextMenuCallback != null);
+
+ MouseInputHandler.Callbacks callbacks = new MouseInputHandler.Callbacks() {
+ @Override
+ public boolean onItemActivated(ItemDetails item, MotionEvent e) {
+ return mActions.openItem(
+ item,
+ ActionHandler.VIEW_TYPE_REGULAR,
+ ActionHandler.VIEW_TYPE_PREVIEW);
+ }
+
+ @Override
+ public boolean onContextClick(MotionEvent e) {
+ return showContextMenuCallback.accept(e);
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+
+ @Override
+ public void focusItem(ItemDetails item) {
+ mFocusHandler.focusDocument(item.getStableId());
+ }
+
+ @Override
+ public void clearFocus() {
+ mFocusHandler.clearFocus();
+ }
+
+ @Override
+ public boolean hasFocusedItem() {
+ return mFocusHandler.hasFocusedItem();
+ }
+
+ @Override
+ public int getFocusedPosition() {
+ return mFocusHandler.getFocusPosition();
+ }
+ };
+
+ return new MouseInputHandler(mSelectionHelper, mDetailsLookup, callbacks);
+ }
+
+ /**
+ * Factory method for input touch delegate. Exists to reduce complexity in the
+ * calling scope.
+ * @param gestureHelper
+ */
+ TouchInputHandler createTouchHandler(
+ GestureSelectionHelper gestureHelper, DragStartListener dragStartListener) {
+ checkArgument(dragStartListener != null);
+
+ TouchInputHandler.Callbacks callbacks = new TouchInputHandler.Callbacks() {
+ @Override
+ public boolean onItemActivated(ItemDetails item, MotionEvent e) {
+ return mActions.openItem(
+ item,
+ ActionHandler.VIEW_TYPE_PREVIEW,
+ ActionHandler.VIEW_TYPE_REGULAR);
+ }
+
+ @Override
+ public boolean onDragInitiated(MotionEvent e) {
+ return dragStartListener.onTouchDragEvent(e);
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+
+ @Override
+ public void focusItem(ItemDetails item) {
+ mFocusHandler.focusDocument(item.getStableId());
+ }
+
+ @Override
+ public void clearFocus() {
+ mFocusHandler.clearFocus();
+ }
+ };
+
+ return new TouchInputHandler(
+ mSelectionHelper, mDetailsLookup, mSelectionPredicate, gestureHelper, callbacks);
+ }
+}
diff --git a/src/com/android/documentsui/dirlist/KeyInputHandler.java b/src/com/android/documentsui/dirlist/KeyInputHandler.java
new file mode 100644
index 0000000..b70438a
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/KeyInputHandler.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import android.view.KeyEvent;
+
+import com.android.documentsui.base.Events;
+import com.android.documentsui.selection.ItemDetailsLookup;
+import com.android.documentsui.selection.MotionInputHandler;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.documentsui.selection.MotionInputHandler.Callbacks;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+import javax.annotation.Nullable;
+
+/**
+ * Class that handles keyboard events on RecyclerView items. The input handler
+ * must be attached directly to a RecyclerView item since, unlike DOM, events
+ * don't appear bubble up.
+ */
+public final class KeyInputHandler extends KeyboardEventListener {
+
+ private final SelectionHelper mSelectionHelper;
+ private final SelectionPredicate mSelectionPredicate;
+ private final Callbacks mCallbacks;
+
+ public KeyInputHandler(
+ SelectionHelper selectionHelper,
+ SelectionPredicate selectionPredicate,
+ Callbacks callbacks) {
+
+ mSelectionHelper = selectionHelper;
+ mSelectionPredicate = selectionPredicate;
+ mCallbacks = callbacks;
+ }
+
+ @Override
+ public boolean onKey(@Nullable ItemDetails details, int keyCode, KeyEvent event) {
+ // Only handle key-down events. This is simpler, consistent with most other UIs, and
+ // enables the handling of repeated key events from holding down a key.
+ if (event.getAction() != KeyEvent.ACTION_DOWN) {
+ return false;
+ }
+
+ // Ignore tab key events. Those should be handled by the top-level key handler.
+ if (keyCode == KeyEvent.KEYCODE_TAB) {
+ return false;
+ }
+
+ // Ignore events sent to Addon Holders.
+ if (details != null) {
+ int itemType = details.getItemViewType();
+ if (itemType == DocumentsAdapter.ITEM_TYPE_HEADER_MESSAGE
+ || itemType == DocumentsAdapter.ITEM_TYPE_INFLATED_MESSAGE
+ || itemType == DocumentsAdapter.ITEM_TYPE_SECTION_BREAK) {
+ return false;
+ }
+ }
+
+ if (mCallbacks.onFocusItem(details, keyCode, event)) {
+ // Handle range selection adjustments. Extending the selection will adjust the
+ // bounds of the in-progress range selection. Each time an unshifted navigation
+ // event is received, the range selection is restarted.
+ if (shouldExtendSelection(details, event)) {
+ if (!mSelectionHelper.isRangeActive()) {
+ // Start a range selection if one isn't active
+ mSelectionHelper.startRange(details.getPosition());
+ }
+ mSelectionHelper.extendRange(details.getPosition());
+ } else {
+ mSelectionHelper.endRange();
+ mSelectionHelper.clearSelection();
+ }
+ return true;
+ }
+
+ // we don't yet have a mechanism to handle opening/previewing multiple documents at once
+ if (mSelectionHelper.getSelection().size() > 1) {
+ return false;
+ }
+
+ return mCallbacks.onItemActivated(details, event);
+ }
+
+ private boolean shouldExtendSelection(ItemDetails item, KeyEvent event) {
+ if (!Events.isNavigationKeyCode(event.getKeyCode()) || !event.isShiftPressed()) {
+ return false;
+ }
+
+ return mSelectionPredicate.canSetStateForId(item.getStableId(), true);
+ }
+
+ public static abstract class Callbacks extends MotionInputHandler.Callbacks {
+ public abstract boolean isInteractiveItem(ItemDetails item, KeyEvent e);
+ public abstract boolean onItemActivated(ItemDetails item, KeyEvent e);
+ public boolean onFocusItem(ItemDetails details, int keyCode, KeyEvent event) {
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/documentsui/dirlist/KeyboardEventListener.java b/src/com/android/documentsui/dirlist/KeyboardEventListener.java
new file mode 100644
index 0000000..fb1fc0a
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/KeyboardEventListener.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import android.view.KeyEvent;
+
+import com.android.documentsui.selection.ItemDetailsLookup;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+
+/**
+ * KeyboardListener is implemented by {@link KeyInputHandler}. The handler
+ * must be called from RecyclerView.Holders in response to keyboard events.
+ */
+public abstract class KeyboardEventListener {
+
+ /**
+ * Handles key events on the view holder.
+ *
+ * @param details The target ItemHolder.
+ * @param keyCode Key code for the event.
+ * @param event KeyEvent for the event.
+ *
+ * @return Whether the event was handled.
+ */
+ public abstract boolean onKey(ItemDetails details, int keyCode, KeyEvent event);
+}
diff --git a/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index 42be8f9..f97410a 100644
--- a/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -23,6 +23,7 @@
import android.database.Cursor;
import android.graphics.Rect;
import android.text.format.Formatter;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
@@ -31,7 +32,6 @@
import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.Shared;
import com.android.documentsui.roots.RootCursorWrapper;
@@ -114,7 +114,7 @@
}
@Override
- public boolean isInDragHotspot(InputEvent event) {
+ public boolean inDragRegion(MotionEvent event) {
// If itemView is activated = selected, then whole region is interactive
if (itemView.isActivated()) {
return true;
@@ -139,7 +139,7 @@
}
@Override
- public boolean isOverDocIcon(InputEvent event) {
+ public boolean inSelectRegion(MotionEvent event) {
Rect iconRect = new Rect();
mIconLayout.getGlobalVisibleRect(iconRect);
@@ -177,7 +177,13 @@
// Note, we don't show any details for any directory...ever.
hasDetails = false;
} else {
- if (mDoc.summary != null) {
+ // Show summary if the file is partial. Otherwise, there tends
+ // to be a bunch of confusing junk in the summary field
+ // as populated by Downlaods (and others). So to make things
+ // simpler and clearer for the user in list view, we only
+ // show the summary if the file is partial >
+ // which we believe to mean actively downloading.
+ if (mDoc.isPartial() && mDoc.summary != null) {
hasDetails = true;
mSummary.setText(mDoc.summary);
mSummary.setVisibility(View.VISIBLE);
diff --git a/src/com/android/documentsui/dirlist/ListeningGestureDetector.java b/src/com/android/documentsui/dirlist/ListeningGestureDetector.java
deleted file mode 100644
index cc81d3f..0000000
--- a/src/com/android/documentsui/dirlist/ListeningGestureDetector.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.dirlist;
-
-import static com.android.documentsui.base.Shared.VERBOSE;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.os.Build;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.OnItemTouchListener;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-
-import com.android.documentsui.base.BooleanConsumer;
-import com.android.documentsui.base.EventHandler;
-import com.android.documentsui.base.Events;
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.base.Events.MotionInputEvent;
-import com.android.documentsui.base.Features;
-import com.android.documentsui.selection.BandController;
-import com.android.documentsui.selection.GestureSelector;
-
-import java.util.function.Consumer;
-
-//Receives event meant for both directory and empty view, and either pass them to
-//{@link UserInputHandler} for simple gestures (Single Tap, Long-Press), or intercept them for
-//other types of gestures (drag n' drop)
-final class ListeningGestureDetector extends GestureDetector implements OnItemTouchListener {
-
- private static final String TAG = "ListeningGestureDetector";
-
- private final Features mFeatures;
- private final GestureSelector mGestureSelector;
- private final EventHandler<InputEvent> mMouseDragListener;
- private final BooleanConsumer mRefreshLayoutEnabler;
- private final BandController mBandController;
- private final MouseDelegate mMouseDelegate = new MouseDelegate();
- private final TouchDelegate mTouchDelegate = new TouchDelegate();
-
- // Currently only initialized on IS_DEBUGGABLE builds.
- private final @Nullable ScaleGestureDetector mScaleDetector;
-
- public ListeningGestureDetector(
- Features features,
- Context context,
- RecyclerView recView,
- EventHandler<InputEvent> mouseDragListener,
- BooleanConsumer refreshLayoutEnabler,
- GestureSelector gestureSelector,
- UserInputHandler<? extends InputEvent> handler,
- @Nullable BandController bandController,
- Consumer<Float> scaleHandler) {
-
- super(context, handler);
-
- mFeatures = features;
- mMouseDragListener = mouseDragListener;
- mRefreshLayoutEnabler = refreshLayoutEnabler;
- mGestureSelector = gestureSelector;
- mBandController = bandController;
- recView.addOnItemTouchListener(this);
-
- mScaleDetector = !Build.IS_DEBUGGABLE
- ? null
- : new ScaleGestureDetector(
- context,
- new ScaleGestureDetector.SimpleOnScaleGestureListener() {
- @Override
- public boolean onScale(ScaleGestureDetector detector) {
- if (VERBOSE) Log.v(TAG,
- "Received scale event: " + detector.getScaleFactor());
- scaleHandler.accept(detector.getScaleFactor());
- return true;
- }
- });
- }
-
- @Override
- public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
- boolean handled = false;
-
- // TODO: Re-wire event handling so that we're not dispatching
- // events to to scaledetector's #onTouchEvent from this
- // #onInterceptTouchEvent touch event.
- if (mFeatures.isGestureScaleEnabled()
- && mScaleDetector != null) {
- mScaleDetector.onTouchEvent(e);
- }
-
- try (InputEvent event = MotionInputEvent.obtain(e, rv)) {
- if (event.isMouseEvent()) {
- if (event.isActionDown()) {
- mRefreshLayoutEnabler.accept(false);
- }
- handled |= mMouseDelegate.onInterceptTouchEvent(event);
- } else {
- // If user has started some gesture while RecyclerView is not at the top, disable
- // refresh
- if (event.isActionDown() && rv.computeVerticalScrollOffset() != 0) {
- mRefreshLayoutEnabler.accept(false);
- }
- handled |= mTouchDelegate.onInterceptTouchEvent(event);
- }
-
-
- if (event.isActionUp()) {
- mRefreshLayoutEnabler.accept(true);
- }
- }
-
- // Forward all events to UserInputHandler.
- // This is necessary since UserInputHandler needs to always see the first DOWN event. Or
- // else all future UP events will be tossed.
- handled |= onTouchEvent(e);
-
- return handled;
- }
-
- @Override
- public void onTouchEvent(RecyclerView rv, MotionEvent e) {
- try (InputEvent event = MotionInputEvent.obtain(e, rv)) {
- if (Events.isMouseEvent(e)) {
- mMouseDelegate.onTouchEvent(event);
- } else {
- mTouchDelegate.onTouchEvent(rv, event);
- }
-
- if (event.isActionUp()) {
- mRefreshLayoutEnabler.accept(true);
- }
- }
-
- // Note: even though this event is being handled as part of gestures such as drag and band,
- // continue forwarding to the GestureDetector. The detector needs to see the entire cluster
- // of events in order to properly interpret other gestures, such as long press.
- onTouchEvent(e);
- }
-
- private class MouseDelegate {
- boolean onInterceptTouchEvent(InputEvent e) {
- if (Events.isMouseDragEvent(e)) {
- return mMouseDragListener.accept(e);
- } else if (mBandController != null &&
- (mBandController.shouldStart(e) || mBandController.shouldStop(e))) {
- return mBandController.onInterceptTouchEvent(e);
- }
- return false;
- }
-
- void onTouchEvent(InputEvent e) {
- if (mBandController != null) {
- mBandController.onTouchEvent(e);
- }
- }
- }
-
- private class TouchDelegate {
- boolean onInterceptTouchEvent(InputEvent e) {
- // Gesture Selector needs to be constantly fed events, so that when a long press does
- // happen, we would have the last DOWN event that occurred to keep track of our anchor
- // point
- return mGestureSelector.onInterceptTouchEvent(e);
- }
-
- // TODO: Make this take just an InputEvent, no RecyclerView
- void onTouchEvent(RecyclerView rv, InputEvent e) {
- mGestureSelector.onTouchEvent(rv, e);
- }
- }
-
- @Override
- public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
-}
diff --git a/src/com/android/documentsui/dirlist/MessageHolder.java b/src/com/android/documentsui/dirlist/MessageHolder.java
index a9a722d..f445347 100644
--- a/src/com/android/documentsui/dirlist/MessageHolder.java
+++ b/src/com/android/documentsui/dirlist/MessageHolder.java
@@ -17,12 +17,10 @@
package com.android.documentsui.dirlist;
import android.content.Context;
+import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.Space;
-import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.base.Events.InputEvent;
-
/**
* Base class for all non-Document Holder classes.
*/
@@ -36,12 +34,7 @@
}
@Override
- public boolean isInSelectionHotspot(InputEvent event) {
+ public boolean inDragRegion(MotionEvent event) {
return false;
}
-
- @Override
- public boolean isInDragHotspot(InputEvent event) {
- return false;
- }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 921917c..99bb63c 100644
--- a/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -23,14 +23,16 @@
import android.database.Cursor;
import android.provider.DocumentsContract.Document;
+import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.ViewGroup;
import com.android.documentsui.Model;
+import com.android.documentsui.Model.Update;
import com.android.documentsui.base.EventListener;
import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.State;
-import com.android.documentsui.Model.Update;
+import com.android.documentsui.selection.SelectionHelper;
import java.util.ArrayList;
import java.util.List;
@@ -109,7 +111,7 @@
@Override
public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
- if (payload.contains(SELECTION_CHANGED_MARKER)) {
+ if (payload.contains(SelectionHelper.SELECTION_CHANGED_MARKER)) {
final boolean selected = mEnv.isSelected(mModelIds.get(position));
holder.setSelected(selected, true);
} else {
@@ -156,7 +158,7 @@
}
@Override
- public String getModelId(int adapterPosition) {
+ public String getStableId(int adapterPosition) {
return mModelIds.get(adapterPosition);
}
@@ -166,11 +168,17 @@
}
@Override
- public List<String> getModelIds() {
+ public List<String> getStableIds() {
return mModelIds;
}
@Override
+ public int getPosition(String id) {
+ int position = mModelIds.indexOf(id);
+ return position >= 0 ? position : RecyclerView.NO_POSITION;
+ }
+
+ @Override
public int getItemViewType(int position) {
return isDirectory(mEnv.getModel(), position)
? ITEM_TYPE_DIRECTORY
@@ -189,15 +197,4 @@
}
return false;
}
-
- @Override
- public void onItemSelectionChanged(String id) {
- int position = mModelIds.indexOf(id);
-
- if (position >= 0) {
- notifyItemChanged(position, SELECTION_CHANGED_MARKER);
- } else {
- Log.w(TAG, "Item change notification received for unknown item: " + id);
- }
- }
}
diff --git a/src/com/android/documentsui/dirlist/MouseDragEventInterceptor.java b/src/com/android/documentsui/dirlist/MouseDragEventInterceptor.java
new file mode 100644
index 0000000..fa40c26
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/MouseDragEventInterceptor.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.view.MotionEvent;
+
+import com.android.documentsui.base.EventHandler;
+import com.android.documentsui.base.Events;
+import com.android.documentsui.selection.BandSelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup;
+import com.android.documentsui.selection.TouchEventRouter;
+
+/**
+ * OnItemTouchListener that helps enable support for drag/drop functionality
+ * in DirectoryFragment.
+ *
+ * <p>This class takes an OnItemTouchListener that is presumably the
+ * one provided by {@link BandSelectionHelper#getListener()}, and
+ * is used in conjunction with the {@link TouchEventRouter}.
+ *
+ * <p>See DirectoryFragment for more details on how this is glued
+ * into DocumetnsUI event handling to make the magic happen.
+ */
+class MouseDragEventInterceptor implements OnItemTouchListener {
+
+ private final ItemDetailsLookup mEventDetailsLookup;
+ private final EventHandler<MotionEvent> mMouseDragListener;
+ private final @Nullable OnItemTouchListener mDelegate;
+
+ public MouseDragEventInterceptor(
+ ItemDetailsLookup eventDetailsLookup,
+ EventHandler<MotionEvent> mouseDragListener,
+ @Nullable OnItemTouchListener delegate) {
+
+ checkArgument(eventDetailsLookup != null);
+ checkArgument(mouseDragListener != null);
+
+ mEventDetailsLookup = eventDetailsLookup;
+ mMouseDragListener = mouseDragListener;
+ mDelegate = delegate;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ if (Events.isMouseDragEvent(e) && mEventDetailsLookup.inItemDragRegion(e)) {
+ return mMouseDragListener.accept(e);
+ } else if (mDelegate != null) {
+ return mDelegate.onInterceptTouchEvent(rv, e);
+ }
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ if (mDelegate != null) {
+ mDelegate.onTouchEvent(rv, e);
+ }
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+}
diff --git a/src/com/android/documentsui/dirlist/RefreshHelper.java b/src/com/android/documentsui/dirlist/RefreshHelper.java
new file mode 100644
index 0000000..a1a5662
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/RefreshHelper.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import static android.support.v4.util.Preconditions.checkState;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.view.MotionEvent;
+
+import com.android.documentsui.base.BooleanConsumer;
+import com.android.documentsui.base.Events;
+
+/**
+ * Class providing support for gluing gesture scaling of the ui into RecyclerView + DocsUI.
+ */
+final class RefreshHelper {
+
+ private final BooleanConsumer mRefreshLayoutEnabler;
+
+ private boolean mAttached;
+
+ public RefreshHelper(BooleanConsumer refreshLayoutEnabler) {
+ mRefreshLayoutEnabler = refreshLayoutEnabler;
+ }
+
+ private boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ if (Events.isMouseEvent(e)) {
+ if (Events.isActionDown(e)) {
+ mRefreshLayoutEnabler.accept(false);
+ }
+ } else {
+ // If user has started some gesture while RecyclerView is not at the top, disable
+ // refresh
+ if (Events.isActionDown(e) && rv.computeVerticalScrollOffset() != 0) {
+ mRefreshLayoutEnabler.accept(false);
+ }
+ }
+
+ if (Events.isActionUp(e)) {
+ mRefreshLayoutEnabler.accept(true);
+ }
+
+ return false;
+ }
+
+ private void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ if (Events.isActionUp(e)) {
+ mRefreshLayoutEnabler.accept(true);
+ }
+ }
+
+ void attach(RecyclerView view) {
+ checkState(!mAttached);
+
+ view.addOnItemTouchListener(
+ new OnItemTouchListener() {
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ RefreshHelper.this.onTouchEvent(rv, e);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ return RefreshHelper.this.onInterceptTouchEvent(rv, e);
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+ });
+
+ mAttached = true;
+ }
+}
diff --git a/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index db9d399..8025a65 100644
--- a/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -107,6 +107,7 @@
return false;
}
});
+ mEditText.requestFocus();
return dialog;
}
diff --git a/src/com/android/documentsui/dirlist/ScaleHelper.java b/src/com/android/documentsui/dirlist/ScaleHelper.java
new file mode 100644
index 0000000..d927fcd
--- /dev/null
+++ b/src/com/android/documentsui/dirlist/ScaleHelper.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.dirlist;
+
+import static android.support.v4.util.Preconditions.checkState;
+import static com.android.documentsui.base.Shared.VERBOSE;
+
+import android.content.Context;
+import android.os.Build;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+
+import com.android.documentsui.base.Features;
+
+import java.util.function.Consumer;
+
+/**
+ * Class providing support for gluing gesture scaling of the ui into RecyclerView + DocsUI.
+ */
+final class ScaleHelper {
+
+ private static final String TAG = "ScaleHelper";
+
+ private final Context mContext;
+ private final Features mFeatures;
+ private final Consumer<Float> mScaleCallback;
+
+ private @Nullable ScaleGestureDetector mScaleDetector;
+
+ public ScaleHelper(Context context, Features features, Consumer<Float> scaleCallback) {
+ mContext = context;
+ mFeatures = features;
+ mScaleCallback = scaleCallback;
+ }
+
+ private boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ // Checking feature is deferred to runtime so the feature can be enabled
+ // after this class has been setup.
+ if (mFeatures.isGestureScaleEnabled() && mScaleDetector != null) {
+ mScaleDetector.onTouchEvent(e);
+ }
+
+ return false;
+ }
+
+ void attach(RecyclerView view) {
+ checkState(Build.IS_DEBUGGABLE);
+ checkState(mScaleDetector == null);
+
+ mScaleDetector = new ScaleGestureDetector(
+ mContext,
+ new ScaleGestureDetector.SimpleOnScaleGestureListener() {
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ if (VERBOSE) Log.v(TAG,
+ "Received scale event: " + detector.getScaleFactor());
+ mScaleCallback.accept(detector.getScaleFactor());
+ return true;
+ }
+ });
+
+ view.addOnItemTouchListener(
+ new OnItemTouchListener() {
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ return ScaleHelper.this.onInterceptTouchEvent(rv, e);
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+ });
+ }
+}
diff --git a/src/com/android/documentsui/selection/SelectionMetadata.java b/src/com/android/documentsui/dirlist/SelectionMetadata.java
similarity index 89%
rename from src/com/android/documentsui/selection/SelectionMetadata.java
rename to src/com/android/documentsui/dirlist/SelectionMetadata.java
index df0f1d6..3ac3a07 100644
--- a/src/com/android/documentsui/selection/SelectionMetadata.java
+++ b/src/com/android/documentsui/dirlist/SelectionMetadata.java
@@ -14,14 +14,11 @@
* limitations under the License.
*/
-package com.android.documentsui.selection;
+package com.android.documentsui.dirlist;
import static com.android.documentsui.base.DocumentInfo.getCursorInt;
import static com.android.documentsui.base.DocumentInfo.getCursorString;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.provider.DocumentsContract.Document;
import android.util.Log;
@@ -30,14 +27,19 @@
import com.android.documentsui.archives.ArchivesProvider;
import com.android.documentsui.base.MimeTypes;
import com.android.documentsui.roots.RootCursorWrapper;
+import com.android.documentsui.selection.SelectionHelper.SelectionObserver;
import java.util.function.Function;
/**
- * A class that holds metadata
+ * A class that aggregates document metadata describing the selection. It can answer questions
+ * like: Can the selection be deleted? and Does the selection contain a folder?
+ *
+ * <p>By collecting information in real-time as the selection changes the need to
+ * traverse the entire selection in order to answer questions is eliminated.
*/
-public class SelectionMetadata
- implements MenuManager.SelectionDetails, SelectionManager.ItemCallback {
+public class SelectionMetadata extends SelectionObserver
+ implements MenuManager.SelectionDetails {
private static final String TAG = "SelectionMetadata";
private final static int FLAG_CAN_DELETE =
diff --git a/src/com/android/documentsui/dirlist/UserInputHandler.java b/src/com/android/documentsui/dirlist/UserInputHandler.java
deleted file mode 100644
index f33284b..0000000
--- a/src/com/android/documentsui/dirlist/UserInputHandler.java
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.dirlist;
-
-import static com.android.documentsui.base.Shared.DEBUG;
-import static com.android.documentsui.base.Shared.VERBOSE;
-
-import android.support.annotation.VisibleForTesting;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-import com.android.documentsui.ActionHandler;
-import com.android.documentsui.base.EventHandler;
-import com.android.documentsui.base.Events;
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.selection.SelectionManager;
-
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-import javax.annotation.Nullable;
-
-/**
- * Grand unified-ish gesture/event listener for items in the directory list.
- */
-public final class UserInputHandler<T extends InputEvent>
- extends GestureDetector.SimpleOnGestureListener
- implements DocumentHolder.KeyboardEventListener {
-
- private static final String TAG = "UserInputHandler";
-
- private ActionHandler mActions;
- private final FocusHandler mFocusHandler;
- private final SelectionManager mSelectionMgr;
- private final Function<MotionEvent, T> mEventConverter;
- private final Predicate<DocumentDetails> mSelectable;
-
- private final EventHandler<InputEvent> mContextMenuClickHandler;
-
- private final EventHandler<InputEvent> mTouchDragListener;
- private final EventHandler<InputEvent> mGestureSelectHandler;
- private final Runnable mPerformHapticFeedback;
-
- private final TouchInputDelegate mTouchDelegate;
- private final MouseInputDelegate mMouseDelegate;
- private final KeyInputHandler mKeyListener;
-
- public UserInputHandler(
- ActionHandler actions,
- FocusHandler focusHandler,
- SelectionManager selectionMgr,
- Function<MotionEvent, T> eventConverter,
- Predicate<DocumentDetails> selectable,
- EventHandler<InputEvent> contextMenuClickHandler,
- EventHandler<InputEvent> touchDragListener,
- EventHandler<InputEvent> gestureSelectHandler,
- Runnable performHapticFeedback) {
-
- mActions = actions;
- mFocusHandler = focusHandler;
- mSelectionMgr = selectionMgr;
- mEventConverter = eventConverter;
- mSelectable = selectable;
- mContextMenuClickHandler = contextMenuClickHandler;
- mTouchDragListener = touchDragListener;
- mGestureSelectHandler = gestureSelectHandler;
- mPerformHapticFeedback = performHapticFeedback;
-
- mTouchDelegate = new TouchInputDelegate();
- mMouseDelegate = new MouseInputDelegate();
- mKeyListener = new KeyInputHandler();
- }
-
- @Override
- public boolean onDown(MotionEvent e) {
- try (T event = mEventConverter.apply(e)) {
- return onDown(event);
- }
- }
-
- @VisibleForTesting
- boolean onDown(T event) {
- return event.isMouseEvent()
- ? mMouseDelegate.onDown(event)
- : mTouchDelegate.onDown(event);
- }
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY) {
- try (T event = mEventConverter.apply(e2)) {
- return onScroll(event);
- }
- }
-
- @VisibleForTesting
- boolean onScroll(T event) {
- return event.isMouseEvent()
- ? mMouseDelegate.onScroll(event)
- : mTouchDelegate.onScroll(event);
- }
-
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- try (T event = mEventConverter.apply(e)) {
- return onSingleTapUp(event);
- }
- }
-
- @VisibleForTesting
- boolean onSingleTapUp(T event) {
- return event.isMouseEvent()
- ? mMouseDelegate.onSingleTapUp(event)
- : mTouchDelegate.onSingleTapUp(event);
- }
-
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- try (T event = mEventConverter.apply(e)) {
- return onSingleTapConfirmed(event);
- }
- }
-
- @VisibleForTesting
- boolean onSingleTapConfirmed(T event) {
- return event.isMouseEvent()
- ? mMouseDelegate.onSingleTapConfirmed(event)
- : mTouchDelegate.onSingleTapConfirmed(event);
- }
-
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- try (T event = mEventConverter.apply(e)) {
- return onDoubleTap(event);
- }
- }
-
- @VisibleForTesting
- boolean onDoubleTap(T event) {
- return event.isMouseEvent()
- ? mMouseDelegate.onDoubleTap(event)
- : mTouchDelegate.onDoubleTap(event);
- }
-
- @Override
- public void onLongPress(MotionEvent e) {
- try (T event = mEventConverter.apply(e)) {
- onLongPress(event);
- }
- }
-
- @VisibleForTesting
- void onLongPress(T event) {
- if (event.isMouseEvent()) {
- mMouseDelegate.onLongPress(event);
- } else {
- mTouchDelegate.onLongPress(event);
- }
- }
-
- // Only events from RecyclerView are fed into UserInputHandler#onDown.
- // ListeningGestureDetector#onTouch directly calls this method to support context menu in empty
- // view
- boolean onRightClick(MotionEvent e) {
- try (T event = mEventConverter.apply(e)) {
- return mMouseDelegate.onRightClick(event);
- }
- }
-
- @Override
- public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event) {
- return mKeyListener.onKey(doc, keyCode, event);
- }
-
- private boolean selectDocument(DocumentDetails doc) {
- assert(doc != null);
- assert(doc.hasModelId());
- mSelectionMgr.toggleSelection(doc.getModelId());
- mSelectionMgr.setSelectionRangeBegin(doc.getAdapterPosition());
-
- // we set the focus on this doc so it will be the origin for keyboard events or shift+clicks
- // if there is only a single item selected, otherwise clear focus
- if (mSelectionMgr.getSelection().size() == 1) {
- mFocusHandler.focusDocument(doc.getModelId());
- } else {
- mFocusHandler.clearFocus();
- }
- return true;
- }
-
- private boolean focusDocument(DocumentDetails doc) {
- assert(doc != null);
- assert(doc.hasModelId());
-
- mSelectionMgr.clearSelection();
- mFocusHandler.focusDocument(doc.getModelId());
- return true;
- }
-
- private void extendSelectionRange(DocumentDetails doc) {
- mSelectionMgr.snapRangeSelection(doc.getAdapterPosition());
- mFocusHandler.focusDocument(doc.getModelId());
- }
-
- boolean isRangeExtension(T event) {
- return event.isShiftKeyDown() && mSelectionMgr.isRangeSelectionActive();
- }
-
- private boolean shouldClearSelection(T event, DocumentDetails doc) {
- return !event.isCtrlKeyDown()
- && !doc.isInSelectionHotspot(event)
- && !doc.isOverDocIcon(event)
- && !isSelected(doc);
- }
-
- private boolean isSelected(DocumentDetails doc) {
- return mSelectionMgr.getSelection().contains(doc.getModelId());
- }
-
- private static final String TTAG = "TouchInputDelegate";
- private final class TouchInputDelegate {
-
- boolean onDown(T event) {
- if (VERBOSE) Log.v(TTAG, "Delegated onDown event.");
- return false;
- }
-
- // Don't consume so the RecyclerView will get the event and will get touch-based scrolling
- boolean onScroll(T event) {
- if (VERBOSE) Log.v(TTAG, "Delegated onScroll event.");
- return false;
- }
-
- boolean onSingleTapUp(T event) {
- if (VERBOSE) Log.v(TTAG, "Delegated onSingleTapUp event.");
- if (!event.isOverModelItem()) {
- if (DEBUG) Log.d(TTAG, "Tap not associated w/ model item. Clearing selection.");
- mSelectionMgr.clearSelection();
- return false;
- }
-
- DocumentDetails doc = event.getDocumentDetails();
- if (mSelectionMgr.hasSelection()) {
- if (isRangeExtension(event)) {
- extendSelectionRange(doc);
- } else if (mSelectionMgr.getSelection().contains(doc.getModelId())) {
- mSelectionMgr.toggleSelection(doc.getModelId());
- } else {
- selectDocument(doc);
- }
-
- return true;
- }
-
- // Touch events select if they occur in the selection hotspot,
- // otherwise they activate.
- return doc.isInSelectionHotspot(event)
- ? selectDocument(doc)
- : mActions.openDocument(doc, ActionHandler.VIEW_TYPE_PREVIEW,
- ActionHandler.VIEW_TYPE_REGULAR);
- }
-
- boolean onSingleTapConfirmed(T event) {
- if (VERBOSE) Log.v(TTAG, "Delegated onSingleTapConfirmed event.");
- return false;
- }
-
- boolean onDoubleTap(T event) {
- if (VERBOSE) Log.v(TTAG, "Delegated onDoubleTap event.");
- return false;
- }
-
- final void onLongPress(T event) {
- if (VERBOSE) Log.v(TTAG, "Delegated onLongPress event.");
- if (!event.isOverModelItem()) {
- if (DEBUG) Log.d(TTAG, "Ignoring LongPress on non-model-backed item.");
- return;
- }
-
- DocumentDetails doc = event.getDocumentDetails();
- boolean handled = false;
- if (isRangeExtension(event)) {
- extendSelectionRange(doc);
- handled = true;
- } else {
- if (!mSelectionMgr.getSelection().contains(doc.getModelId())) {
- selectDocument(doc);
- // If we cannot select it, we didn't apply anchoring - therefore should not
- // start gesture selection
- if (mSelectable.test(doc)) {
- mGestureSelectHandler.accept(event);
- handled = true;
- }
- } else {
- // We only initiate drag and drop on long press for touch to allow regular
- // touch-based scrolling
- mTouchDragListener.accept(event);
- handled = true;
- }
- }
- if (handled) {
- mPerformHapticFeedback.run();
- }
- }
- }
-
- private static final String MTAG = "MouseInputDelegate";
- private final class MouseInputDelegate {
- // The event has been handled in onSingleTapUp
- private boolean mHandledTapUp;
- // true when the previous event has consumed a right click motion event
- private boolean mHandledOnDown;
-
- boolean onDown(T event) {
- if (VERBOSE) Log.v(MTAG, "Delegated onDown event.");
- if (event.isSecondaryButtonPressed()
- || (event.isAltKeyDown() && event.isPrimaryButtonPressed())) {
- mHandledOnDown = true;
- return onRightClick(event);
- }
-
- return false;
- }
-
- // Don't scroll content window in response to mouse drag
- boolean onScroll(T event) {
- if (VERBOSE) Log.v(MTAG, "Delegated onScroll event.");
- // If it's two-finger trackpad scrolling, we want to scroll
- return !event.isTouchpadScroll();
- }
-
- boolean onSingleTapUp(T event) {
- if (VERBOSE) Log.v(MTAG, "Delegated onSingleTapUp event.");
-
- // See b/27377794. Since we don't get a button state back from UP events, we have to
- // explicitly save this state to know whether something was previously handled by
- // DOWN events or not.
- if (mHandledOnDown) {
- if (VERBOSE) Log.v(MTAG, "Ignoring onSingleTapUp, previously handled in onDown.");
- mHandledOnDown = false;
- return false;
- }
-
- if (!event.isOverModelItem()) {
- if (DEBUG) Log.d(MTAG, "Tap not associated w/ model item. Clearing selection.");
- mSelectionMgr.clearSelection();
- mFocusHandler.clearFocus();
- return false;
- }
-
- if (event.isTertiaryButtonPressed()) {
- if (DEBUG) Log.d(MTAG, "Ignoring middle click");
- return false;
- }
-
- DocumentDetails doc = event.getDocumentDetails();
- if (mSelectionMgr.hasSelection()) {
- if (isRangeExtension(event)) {
- extendSelectionRange(doc);
- } else {
- if (shouldClearSelection(event, doc)) {
- mSelectionMgr.clearSelection();
- }
- if (isSelected(doc)) {
- mSelectionMgr.toggleSelection(doc.getModelId());
- mFocusHandler.clearFocus();
- } else {
- selectOrFocusItem(event);
- }
- }
- mHandledTapUp = true;
- return true;
- }
-
- return false;
- }
-
- boolean onSingleTapConfirmed(T event) {
- if (VERBOSE) Log.v(MTAG, "Delegated onSingleTapConfirmed event.");
- if (mHandledTapUp) {
- if (VERBOSE) Log.v(MTAG, "Ignoring onSingleTapConfirmed, previously handled in onSingleTapUp.");
- mHandledTapUp = false;
- return false;
- }
-
- if (mSelectionMgr.hasSelection()) {
- return false; // should have been handled by onSingleTapUp.
- }
-
- if (!event.isOverItem()) {
- if (DEBUG) Log.d(MTAG, "Ignoring Confirmed Tap on non-item.");
- return false;
- }
-
- if (event.isTertiaryButtonPressed()) {
- if (DEBUG) Log.d(MTAG, "Ignoring middle click");
- return false;
- }
-
- @Nullable DocumentDetails doc = event.getDocumentDetails();
- if (doc == null || !doc.hasModelId()) {
- Log.w(MTAG, "Ignoring Confirmed Tap. No document details associated w/ event.");
- return false;
- }
-
- if (mFocusHandler.hasFocusedItem() && event.isShiftKeyDown()) {
- mSelectionMgr.formNewSelectionRange(mFocusHandler.getFocusPosition(),
- doc.getAdapterPosition());
- } else {
- selectOrFocusItem(event);
- }
- return true;
- }
-
- boolean onDoubleTap(T event) {
- if (VERBOSE) Log.v(MTAG, "Delegated onDoubleTap event.");
- mHandledTapUp = false;
-
- if (!event.isOverModelItem()) {
- if (DEBUG) Log.d(MTAG, "Ignoring DoubleTap on non-model-backed item.");
- return false;
- }
-
- if (event.isTertiaryButtonPressed()) {
- if (DEBUG) Log.d(MTAG, "Ignoring middle click");
- return false;
- }
-
- DocumentDetails doc = event.getDocumentDetails();
- return mActions.openDocument(doc, ActionHandler.VIEW_TYPE_REGULAR,
- ActionHandler.VIEW_TYPE_PREVIEW);
- }
-
- final void onLongPress(T event) {
- if (VERBOSE) Log.v(MTAG, "Delegated onLongPress event.");
- return;
- }
-
- private boolean onRightClick(T event) {
- if (VERBOSE) Log.v(MTAG, "Delegated onRightClick event.");
- if (event.isOverModelItem()) {
- DocumentDetails doc = event.getDocumentDetails();
- if (!mSelectionMgr.getSelection().contains(doc.getModelId())) {
- mSelectionMgr.clearSelection();
- selectDocument(doc);
- }
- }
-
- // We always delegate final handling of the event,
- // since the handler might want to show a context menu
- // in an empty area or some other weirdo view.
- return mContextMenuClickHandler.accept(event);
- }
-
- private void selectOrFocusItem(T event) {
- if (event.isOverDocIcon() || event.isCtrlKeyDown()) {
- selectDocument(event.getDocumentDetails());
- } else {
- focusDocument(event.getDocumentDetails());
- }
- }
- }
-
- private final class KeyInputHandler {
- // TODO: Refactor FocusManager to depend only on DocumentDetails so we can eliminate
- // difficult to test dependency on DocumentHolder.
-
- boolean onKey(@Nullable DocumentHolder doc, int keyCode, KeyEvent event) {
- // Only handle key-down events. This is simpler, consistent with most other UIs, and
- // enables the handling of repeated key events from holding down a key.
- if (event.getAction() != KeyEvent.ACTION_DOWN) {
- return false;
- }
-
- // Ignore tab key events. Those should be handled by the top-level key handler.
- if (keyCode == KeyEvent.KEYCODE_TAB) {
- return false;
- }
-
- // Ignore events sent to Addon Holders.
- if (doc != null) {
- int itemType = doc.getItemViewType();
- if (itemType == DocumentsAdapter.ITEM_TYPE_HEADER_MESSAGE
- || itemType == DocumentsAdapter.ITEM_TYPE_INFLATED_MESSAGE
- || itemType == DocumentsAdapter.ITEM_TYPE_SECTION_BREAK) {
- return false;
- }
- }
-
- if (mFocusHandler.handleKey(doc, keyCode, event)) {
- // Handle range selection adjustments. Extending the selection will adjust the
- // bounds of the in-progress range selection. Each time an unshifted navigation
- // event is received, the range selection is restarted.
- if (shouldExtendSelection(doc, event)) {
- if (!mSelectionMgr.isRangeSelectionActive()) {
- // Start a range selection if one isn't active
- mSelectionMgr.startRangeSelection(doc.getAdapterPosition());
- }
- mSelectionMgr.snapRangeSelection(mFocusHandler.getFocusPosition());
- } else {
- mSelectionMgr.endRangeSelection();
- mSelectionMgr.clearSelection();
- }
- return true;
- }
-
- // we don't yet have a mechanism to handle opening/previewing multiple documents at once
- if (mSelectionMgr.getSelection().size() > 1) {
- return false;
- }
-
- // Handle enter key events
- switch (keyCode) {
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_BUTTON_A:
- return mActions.openDocument(doc, ActionHandler.VIEW_TYPE_REGULAR,
- ActionHandler.VIEW_TYPE_PREVIEW);
- case KeyEvent.KEYCODE_SPACE:
- return mActions.openDocument(doc, ActionHandler.VIEW_TYPE_PREVIEW,
- ActionHandler.VIEW_TYPE_NONE);
- }
-
- return false;
- }
-
- private boolean shouldExtendSelection(DocumentDetails doc, KeyEvent event) {
- if (!Events.isNavigationKeyCode(event.getKeyCode()) || !event.isShiftPressed()) {
- return false;
- }
-
- return mSelectable.test(doc);
- }
- }
-}
diff --git a/src/com/android/documentsui/files/ActionHandler.java b/src/com/android/documentsui/files/ActionHandler.java
index 922f0c0..715e6c9 100644
--- a/src/com/android/documentsui/files/ActionHandler.java
+++ b/src/com/android/documentsui/files/ActionHandler.java
@@ -25,7 +25,9 @@
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.provider.DocumentsContract;
+import android.text.TextUtils;
import android.util.Log;
import android.view.DragEvent;
@@ -56,12 +58,13 @@
import com.android.documentsui.clipping.DocumentClipper;
import com.android.documentsui.clipping.UrisSupplier;
import com.android.documentsui.dirlist.AnimationView;
-import com.android.documentsui.dirlist.DocumentDetails;
import com.android.documentsui.files.ActionHandler.Addons;
import com.android.documentsui.inspector.InspectorActivity;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.roots.ProvidersAccess;
+import com.android.documentsui.selection.MutableSelection;
import com.android.documentsui.selection.Selection;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
import com.android.documentsui.services.FileOperation;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperations;
@@ -187,12 +190,12 @@
}
@Override
- public boolean openDocument(DocumentDetails details, @ViewType int type,
+ public boolean openItem(ItemDetails details, @ViewType int type,
@ViewType int fallback) {
- DocumentInfo doc = mModel.getDocument(details.getModelId());
+ DocumentInfo doc = mModel.getDocument(details.getStableId());
if (doc == null) {
Log.w(TAG,
- "Can't view item. No Document available for modeId: " + details.getModelId());
+ "Can't view item. No Document available for modeId: " + details.getStableId());
return false;
}
@@ -218,7 +221,7 @@
}
private Selection getSelectedOrFocused() {
- final Selection selection = this.getStableSelection();
+ final MutableSelection selection = this.getStableSelection();
if (selection.isEmpty()) {
String focusModelId = mFocusHandler.getFocusModelId();
if (focusModelId != null) {
@@ -508,6 +511,14 @@
return;
}
+ // For APKs, even if the type is preview, we send an ACTION_VIEW intent to allow
+ // PackageManager to install it. This allows users to install APKs from any root.
+ // The Downloads special case is handled above in #manageDocument.
+ if (MimeTypes.isApkType(doc.mimeType)) {
+ viewDocument(doc);
+ return;
+ }
+
switch (type) {
case VIEW_TYPE_REGULAR:
if (viewDocument(doc)) {
@@ -678,11 +689,26 @@
public void showInspector(DocumentInfo doc) {
Metrics.logUserAction(mActivity, Metrics.USER_ACTION_INSPECTOR);
Intent intent = new Intent(mActivity, InspectorActivity.class);
+ intent.setData(doc.derivedUri);
+
+ // permit the display of debug info about the file.
intent.putExtra(
Shared.EXTRA_SHOW_DEBUG,
- mFeatures.isDebugSupportEnabled()
- || DebugFlags.getDocumentDetailsEnabled());
- intent.setData(doc.derivedUri);
+ mFeatures.isDebugSupportEnabled() &&
+ (Build.IS_DEBUGGABLE || DebugFlags.getDocumentDetailsEnabled()));
+
+ // The "root document" (top level folder in a root) don't usually have a
+ // human friendly display name. That's because we've never shown the root
+ // folder's name to anyone.
+ // For that reason when the doc being inspected is the root folder,
+ // we override the displayName of the doc w/ the Root's name instead.
+ // The Root's name is shown to the user in the sidebar.
+ if (doc.isDirectory() && mState.stack.size() == 1 && mState.stack.get(0).equals(doc)) {
+ RootInfo root = mActivity.getCurrentRoot();
+ // Recents root title isn't defined, but inspector is disabled for recents root folder.
+ assert !TextUtils.isEmpty(root.title);
+ intent.putExtra(Intent.EXTRA_TITLE, root.title);
+ }
mActivity.startActivity(intent);
}
diff --git a/src/com/android/documentsui/files/FilesActivity.java b/src/com/android/documentsui/files/FilesActivity.java
index 50ba2ff..a6efbb0 100644
--- a/src/com/android/documentsui/files/FilesActivity.java
+++ b/src/com/android/documentsui/files/FilesActivity.java
@@ -21,14 +21,13 @@
import android.app.ActivityManager.TaskDescription;
import android.app.FragmentManager;
import android.content.Intent;
-import android.content.Context;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.CallSuper;
@@ -39,6 +38,7 @@
import com.android.documentsui.ActionModeController;
import com.android.documentsui.BaseActivity;
+import com.android.documentsui.DocsSelectionHelper;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.FocusManager;
import com.android.documentsui.Injector;
@@ -57,7 +57,6 @@
import com.android.documentsui.dirlist.AnimationView.AnimationType;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.prefs.ScopedPreferences;
-import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.sidebar.RootsFragment;
import com.android.documentsui.ui.DialogController;
@@ -105,7 +104,7 @@
super.onCreate(icicle);
DocumentClipper clipper = DocumentsApplication.getDocumentClipper(this);
- mInjector.selectionMgr = new SelectionManager(SelectionManager.MODE_MULTIPLE);
+ mInjector.selectionMgr = DocsSelectionHelper.createMultiSelect();
mInjector.focusManager = new FocusManager(
mInjector.features,
@@ -352,6 +351,9 @@
case R.id.option_menu_select_all:
mInjector.actions.selectAllFiles();
break;
+ case R.id.option_menu_inspect:
+ mInjector.actions.showInspector(getCurrentDirectory());
+ break;
default:
return super.onOptionsItemSelected(item);
}
diff --git a/src/com/android/documentsui/files/MenuManager.java b/src/com/android/documentsui/files/MenuManager.java
index 4754c6d..60cf11b 100644
--- a/src/com/android/documentsui/files/MenuManager.java
+++ b/src/com/android/documentsui/files/MenuManager.java
@@ -29,23 +29,23 @@
import android.view.View;
import com.android.documentsui.R;
+import com.android.documentsui.MenuManager.SelectionDetails;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.Features;
import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.queries.SearchViewManager;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.SelectionHelper;
import java.util.List;
-import java.util.function.Function;
import java.util.function.IntFunction;
public final class MenuManager extends com.android.documentsui.MenuManager {
private final Features mFeatures;
private final Context mContext;
- private final SelectionManager mSelectionManager;
+ private final SelectionHelper mSelectionManager;
private final Lookup<String, Uri> mUriLookup;
private final Lookup<String, String> mAppNameLookup;
@@ -55,10 +55,12 @@
State displayState,
DirectoryDetails dirDetails,
Context context,
- SelectionManager selectionManager,
+ SelectionHelper selectionManager,
Lookup<String, String> appNameLookup,
Lookup<String, Uri> uriLookup) {
+
super(searchManager, displayState, dirDetails);
+
mFeatures = features;
mContext = context;
mSelectionManager = selectionManager;
@@ -265,10 +267,16 @@
}
@Override
- protected void updateInspector(MenuItem properties, SelectionDetails selectionDetails) {
+ protected void updateInspect(MenuItem inspect) {
+ inspect.setVisible(mFeatures.isInspectorEnabled());
+ inspect.setEnabled(mFeatures.isInspectorEnabled() && !mState.stack.isRecents());
+ }
+
+ @Override
+ protected void updateInspect(MenuItem inspect, SelectionDetails selectionDetails) {
boolean visible = mFeatures.isInspectorEnabled();
- properties.setVisible(visible);
- properties.setEnabled(visible && selectionDetails.size() == 1);
+ inspect.setVisible(visible);
+ inspect.setEnabled(visible && selectionDetails.size() <= 1);
}
@Override
diff --git a/src/com/android/documentsui/files/QuickViewIntentBuilder.java b/src/com/android/documentsui/files/QuickViewIntentBuilder.java
index 7eef89a..8511065 100644
--- a/src/com/android/documentsui/files/QuickViewIntentBuilder.java
+++ b/src/com/android/documentsui/files/QuickViewIntentBuilder.java
@@ -62,6 +62,7 @@
private static final String[] FULL_FEATURES = {
QuickViewConstants.FEATURE_VIEW,
QuickViewConstants.FEATURE_EDIT,
+ QuickViewConstants.FEATURE_DELETE,
QuickViewConstants.FEATURE_SEND,
QuickViewConstants.FEATURE_DOWNLOAD,
QuickViewConstants.FEATURE_PRINT
diff --git a/src/com/android/documentsui/inspector/DateUtils.java b/src/com/android/documentsui/inspector/DateUtils.java
new file mode 100644
index 0000000..c4138ed
--- /dev/null
+++ b/src/com/android/documentsui/inspector/DateUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import android.text.format.DateFormat;
+import java.util.Locale;
+
+/**
+ * Helper methods for dealing with dates.
+ */
+final class DateUtils {
+ /**
+ * This small helper method combines two different DateFormat subclasses in order to format
+ * both the date and the time based on user locale.
+ * @param date Unix timestamp
+ * @return formatted String of date
+ */
+ static String formatDate(long date) {
+ String format = DateFormat.getBestDateTimePattern(Locale.getDefault(),
+ "MMM dd, yyyy, hh:mm");
+ return DateFormat.format(format, date).toString();
+ }
+}
diff --git a/src/com/android/documentsui/inspector/DebugView.java b/src/com/android/documentsui/inspector/DebugView.java
index 581e754..03427e5 100644
--- a/src/com/android/documentsui/inspector/DebugView.java
+++ b/src/com/android/documentsui/inspector/DebugView.java
@@ -15,18 +15,38 @@
*/
package com.android.documentsui.inspector;
+import android.annotation.StringRes;
import android.content.Context;
+import android.content.res.Resources;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
import android.util.AttributeSet;
+import android.widget.TextView;
import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
+import com.android.documentsui.base.DummyLookup;
+import com.android.documentsui.base.Lookup;
+import com.android.documentsui.inspector.InspectorController.DebugDisplay;
-import java.util.function.Consumer;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executor;
/**
- * Organizes and Displays the basic details about a file
+ * Organizes and Displays the debug information about a file. This view
+ * should only be made visible when build is debuggable and system policies
+ * allow debug "stuff".
*/
-public class DebugView extends TableView implements Consumer<DocumentInfo> {
+public class DebugView extends TableView implements DebugDisplay {
+
+ private final Context mContext;
+ private final Resources mRes;
+ private Lookup<String, Executor> mExecutors = new DummyLookup<>();
public DebugView(Context context) {
this(context, null);
@@ -38,29 +58,88 @@
public DebugView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ mContext = context;
+ mRes = context.getResources();
+ }
+
+ void init(Lookup<String, Executor> executors) {
+ assert executors != null;
+ setBackgroundColor(0xFFFFFFFF); // it's just debug. We do what we want!
+ mExecutors = executors;
}
@Override
public void accept(DocumentInfo info) {
- setTitle(this, R.string.inspector_debug_section);
+ setTitle(R.string.inspector_debug_section, false);
- put("Content uri", info.derivedUri);
- put("Document id", info.documentId);
- put("Mimetype: ", info.mimeType);
- put("Is archive", info.isArchive());
- put("Is container", info.isContainer());
- put("Is partial", info.isPartial());
- put("Is virtual", info.isVirtual());
- put("Supports create", info.isCreateSupported());
- put("Supports delete", info.isDeleteSupported());
- put("Supports rename", info.isRenameSupported());
- put("Supports settings", info.isSettingsSupported());
- put("Supports thumbnail", info.isThumbnailSupported());
- put("Supports weblink", info.isWeblinkSupported());
- put("Supports write", info.isWriteSupported());
+ put(R.string.debug_content_uri, info.derivedUri.toString());
+ put(R.string.debug_document_id, info.documentId);
+ put(R.string.debug_raw_mimetype, info.mimeType);
+ put(R.string.debug_stream_types, "-");
+ put(R.string.debug_raw_size, NumberFormat.getInstance().format(info.size));
+ put(R.string.debug_is_archive, info.isArchive());
+ put(R.string.debug_is_container, info.isContainer());
+ put(R.string.debug_is_partial, info.isPartial());
+ put(R.string.debug_is_virtual, info.isVirtual());
+ put(R.string.debug_supports_create, info.isCreateSupported());
+ put(R.string.debug_supports_delete, info.isDeleteSupported());
+ put(R.string.debug_supports_metadata, info.isMetadataSupported());
+ put(R.string.debug_supports_remove, info.isRemoveSupported());
+ put(R.string.debug_supports_rename, info.isRenameSupported());
+ put(R.string.debug_supports_settings, info.isSettingsSupported());
+ put(R.string.debug_supports_thumbnail, info.isThumbnailSupported());
+ put(R.string.debug_supports_weblink, info.isWeblinkSupported());
+ put(R.string.debug_supports_write, info.isWriteSupported());
+
+ // Load Document stream types of the file. For virtual files, this should be
+ // something other than the primary type of the file.
+ Executor executor = mExecutors.lookup(info.derivedUri.getAuthority());
+ if (executor != null) {
+ new AsyncTask<Void, Void, String[]>() {
+ @Override
+ protected String[] doInBackground(Void... params) {
+ return mContext.getContentResolver().getStreamTypes(info.derivedUri, "*/*");
+ }
+
+ @Override
+ protected void onPostExecute(String[] streamTypes) {
+ put(R.string.debug_stream_types,
+ streamTypes != null ? Arrays.toString(streamTypes) : "[]");
+ }
+ }.executeOnExecutor(executor, (Void[]) null);
+ }
}
- private void put(String key, Object value) {
- put(key, String.valueOf(value));
+ @Override
+ public void accept(Bundle metadata) {
+ if (metadata == null) {
+ return;
+ }
+
+ String[] types = metadata.getStringArray(DocumentsContract.METADATA_TYPES);
+ if (types == null) {
+ return;
+ }
+
+ for (String type : types) {
+ dumpMetadata(type, metadata.getBundle(type));
+ }
+ }
+
+ private void dumpMetadata(String type, Bundle bundle) {
+ String title = mContext.getResources().getString(
+ R.string.inspector_debug_metadata_section);
+ putTitle(String.format(title, type), true);
+ List<String> keys = new ArrayList<>(bundle.keySet());
+ Collections.sort(keys);
+ for (String key : keys) {
+ put(key, String.valueOf(bundle.get(key)));
+ }
+ }
+
+ private void put(@StringRes int key, boolean value) {
+ KeyValueRow row = put(mRes.getString(key), String.valueOf(value));
+ TextView valueView = ((TextView) row.findViewById(R.id.table_row_value));
+ valueView.setTextColor(value ? 0xFF006400 : 0xFF9A2020);
}
}
diff --git a/src/com/android/documentsui/inspector/DetailsView.java b/src/com/android/documentsui/inspector/DetailsView.java
index 5497068..75b3cac 100644
--- a/src/com/android/documentsui/inspector/DetailsView.java
+++ b/src/com/android/documentsui/inspector/DetailsView.java
@@ -16,7 +16,6 @@
package com.android.documentsui.inspector;
import android.content.Context;
-import android.text.format.DateFormat;
import android.text.format.Formatter;
import android.util.AttributeSet;
@@ -44,26 +43,33 @@
}
@Override
- public void accept(DocumentInfo info) {
+ public void accept(DocumentInfo doc) {
Lookup<String, String> fileTypeLookup =
DocumentsApplication.getFileTypeLookup(getContext());
- put(R.string.sort_dimension_file_type, fileTypeLookup.lookup(info.mimeType));
+ String mimeType = fileTypeLookup.lookup(doc.mimeType);
+
+ put(R.string.sort_dimension_file_type, mimeType);
// TODO: Each of these rows need to be removed if the condition is false and previously
// set.
- if (info.size > 0) {
- put(R.string.sort_dimension_size, Formatter.formatFileSize(getContext(), info.size));
+ if (doc.size >= 0 && !doc.isDirectory()) {
+ put(R.string.sort_dimension_size, Formatter.formatFileSize(getContext(), doc.size));
}
- if (info.lastModified > 0) {
- put(R.string.sort_dimension_date,
- DateFormat.getDateFormat(getContext()).format(info.lastModified));
+ if (doc.lastModified > 0) {
+ put(R.string.sort_dimension_date, DateUtils.formatDate(doc.lastModified));
}
- if (info.summary != null) {
- put(R.string.sort_dimension_summary, info.summary);
+ // We only show summary field when doc is partial (meaning an active download).
+ // The rest of the time "summary" tends to be less than useful. For example
+ // after a download is completed DownloadsProvider include the orig filename
+ // in the summary field. This is confusing to folks in-and-if-itself, but
+ // after the file is renamed, it creates even more confusion (since it still
+ // shows the original). For that reason, and others. We only display on partial files.
+ if (doc.isPartial() && doc.summary != null) {
+ put(R.string.sort_dimension_summary, doc.summary);
}
}
diff --git a/src/com/android/documentsui/inspector/GpsCoordinatesTextClassifier.java b/src/com/android/documentsui/inspector/GpsCoordinatesTextClassifier.java
new file mode 100644
index 0000000..a0a95a2
--- /dev/null
+++ b/src/com/android/documentsui/inspector/GpsCoordinatesTextClassifier.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.LocaleList;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationManager;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextSelection;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Checks if a TextView has a latitude and longitude. If so shows the default maps app to open
+ * those coordinates.
+ *
+ * Example - textView.setTextClassifier(new GpsCoordinatesTextClassifier(context, intent));
+ */
+final class GpsCoordinatesTextClassifier implements TextClassifier {
+
+ // Checks for latitude and longitude points, latitude ranges -90.0 to 90.0 and longitude
+ // ranges -180.0 to 180.0 Valid entries can be of the format "0,0", "0, 0" and "0.0, 0.0"
+ // in the mentioned range.
+ private static final String geoPattern
+ = "-?(90(\\.0*)?|[1-8]?[0-9](\\.[0-9]*)?), *-?(180("
+ + "\\.0*)?|([1][0-7][0-9]|[0-9]?[0-9])(\\.[0-9]*)?)";
+ private static final Pattern sGeoPattern = Pattern.compile(geoPattern);
+
+ private final TextClassifier mSystemClassifier;
+ private final PackageManager mPackageManager;
+
+ public GpsCoordinatesTextClassifier(PackageManager pm, TextClassifier classifier) {
+ assert pm != null;
+ assert classifier != null;
+ mPackageManager = pm;
+ mSystemClassifier = classifier;
+ }
+
+ public static GpsCoordinatesTextClassifier create(Context context) {
+ return new GpsCoordinatesTextClassifier(
+ context.getPackageManager(),
+ context.getSystemService(TextClassificationManager.class).getTextClassifier());
+ }
+
+ // TODO: add support for local specific formatting
+ @Override
+ public TextClassification classifyText(
+ CharSequence text, int start, int end, LocaleList localeList) {
+
+ CharSequence sequence = text.subSequence(start, end);
+ if (isGeoSequence(sequence)) {
+
+ Intent intent = new Intent(Intent.ACTION_VIEW)
+ .setData(Uri.parse(String.format("geo:0,0?q=%s", sequence)));
+
+ final ResolveInfo info = mPackageManager.resolveActivity(intent, 0);
+ if (info != null) {
+
+ return new TextClassification.Builder()
+ .setText(sequence.toString())
+ .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
+ .setIcon(info.loadIcon(mPackageManager))
+ .setLabel(info.loadLabel(mPackageManager).toString())
+ .setIntent(intent)
+ .build();
+ }
+ }
+
+ // return default if text was not latitude, longitude or we couldn't find an application
+ // to handle the geo intent.
+ return mSystemClassifier.classifyText(text, start, end, localeList);
+ }
+
+ @Override
+ public TextSelection suggestSelection(
+ CharSequence context, int start, int end, LocaleList localeList) {
+
+ // Show map action menu popup when entire TextView is selected.
+ final int[] boundaries = {0, context.length()};
+
+ if (boundaries != null) {
+ return new TextSelection.Builder(boundaries[0], boundaries[1])
+ .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
+ .build();
+ }
+ return mSystemClassifier.suggestSelection(context, start, end, localeList);
+ }
+
+ private static boolean isGeoSequence(CharSequence text) {
+ return sGeoPattern.matcher(text).matches();
+ }
+}
diff --git a/src/com/android/documentsui/inspector/HeaderTextSelector.java b/src/com/android/documentsui/inspector/HeaderTextSelector.java
new file mode 100644
index 0000000..5530fbe
--- /dev/null
+++ b/src/com/android/documentsui/inspector/HeaderTextSelector.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.text.Spannable;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.TextView;
+
+/**
+ * Selects all or part of a textview.
+ */
+ public final class HeaderTextSelector implements ActionMode.Callback {
+
+ private final TextView mText;
+ private final Selector mSelector;
+
+ public HeaderTextSelector(TextView text, Selector selector) {
+ checkArgument(text != null);
+ checkArgument(selector != null);
+ mText = text;
+ mSelector = selector;
+ }
+
+ // An action mode is created when the user selects text. This method is called where
+ // we force it to select only the filename in the header. Meaning the name of the file would
+ // be selected but the extension would not.
+ @Override
+ public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
+ CharSequence value = mText.getText();
+ if (value instanceof Spannable) {
+ mSelector.select((Spannable) value, 0, getLengthOfFilename(value));
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
+ return true;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
+ return false;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode actionMode) {}
+
+ /**
+ * Gets the length of the inspector header for selection.
+ *
+ * Example:
+ * filename.txt returns the end index needed to select "filename".
+ *
+ * @return the index of the last character in the filename
+ */
+ private static int getLengthOfFilename(CharSequence text) {
+ String title = text.toString();
+ if (title != null) {
+ int index = title.indexOf('.');
+ if (index > 0) {
+ return index;
+ }
+ }
+
+ return text.length();
+ }
+
+ public interface Selector {
+ void select(Spannable text, int start, int stop);
+ }
+}
diff --git a/src/com/android/documentsui/inspector/HeaderView.java b/src/com/android/documentsui/inspector/HeaderView.java
index 835af77..c411082 100644
--- a/src/com/android/documentsui/inspector/HeaderView.java
+++ b/src/com/android/documentsui/inspector/HeaderView.java
@@ -20,6 +20,8 @@
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
+import android.text.Selection;
+import android.text.Spannable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -29,18 +31,20 @@
import android.widget.TextView;
import com.android.documentsui.ProviderExecutor;
+import com.android.documentsui.R;
import com.android.documentsui.ThumbnailLoader;
import com.android.documentsui.base.Display;
import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.R;
+import com.android.documentsui.inspector.InspectorController.HeaderDisplay;
+
import java.util.function.Consumer;
+import javax.annotation.Nullable;
+
/**
* Organizes and displays the title and thumbnail for a given document
*/
-public final class HeaderView extends RelativeLayout implements Consumer<DocumentInfo> {
-
- private static final String TAG = HeaderView.class.getCanonicalName();
+public final class HeaderView extends RelativeLayout implements HeaderDisplay {
private final Context mContext;
private final View mHeader;
@@ -68,63 +72,55 @@
int width = (int) Display.screenWidth((Activity)context);
int height = mContext.getResources().getDimensionPixelSize(R.dimen.inspector_header_height);
mImageDimensions = new Point(width, height);
+ addView(mHeader);
}
@Override
- public void accept(DocumentInfo info) {
- if (!hasHeader()) {
- addView(mHeader);
- }
-
- if (!hasHeaderImage()) {
- if (info.isDirectory()) {
- loadFileIcon(info);
- } else {
- loadHeaderImage(info);
- }
- }
- mTitle.setText(info.displayName);
+ public void accept(DocumentInfo info, String displayName) {
+ loadHeaderImage(info);
+ mTitle.setText(displayName);
+ mTitle.setCustomSelectionActionModeCallback(
+ new HeaderTextSelector(mTitle, this::selectText));
}
- private boolean hasHeader() {
- for (int i = 0; i < getChildCount(); i++) {
- if (getChildAt(i).equals(mHeader)) {
- return true;
- }
- }
- return false;
+ private void selectText(Spannable text, int start, int stop) {
+ Selection.setSelection(text, start, stop);
}
- private void loadFileIcon(DocumentInfo info) {
- Drawable mimeIcon = mContext.getContentResolver()
- .getTypeDrawable(info.mimeType);
- mThumbnail.setScaleType(ScaleType.FIT_CENTER);
- mThumbnail.setImageDrawable(mimeIcon);
- }
-
- private void loadHeaderImage(DocumentInfo info) {
-
- Consumer<Bitmap> callback = new Consumer<Bitmap>() {
- @Override
- public void accept(Bitmap bitmap) {
- if (bitmap != null) {
- mThumbnail.setScaleType(ScaleType.CENTER_CROP);
- mThumbnail.setImageBitmap(bitmap);
- } else {
- loadFileIcon(info);
+ private void loadHeaderImage(DocumentInfo doc) {
+ if (!doc.isThumbnailSupported()) {
+ showImage(doc, null);
+ } else {
+ Consumer<Bitmap> callback = new Consumer<Bitmap>() {
+ @Override
+ public void accept(Bitmap thumbnail) {
+ showImage(doc, thumbnail);
}
- mThumbnail.animate().alpha(1.0f).start();
- }
- };
-
- // load the thumbnail async.
- final ThumbnailLoader task = new ThumbnailLoader(info.derivedUri, mThumbnail,
- mImageDimensions, info.lastModified, callback, false);
- task.executeOnExecutor(ProviderExecutor.forAuthority(info.derivedUri.getAuthority()),
- info.derivedUri);
+ };
+ // load the thumbnail async.
+ final ThumbnailLoader task = new ThumbnailLoader(doc.derivedUri, mThumbnail,
+ mImageDimensions, doc.lastModified, callback, false);
+ task.executeOnExecutor(ProviderExecutor.forAuthority(doc.derivedUri.getAuthority()),
+ doc.derivedUri);
+ }
}
- private boolean hasHeaderImage() {
- return mThumbnail.getAlpha() == 1.0f;
+ /**
+ * Shows the supplied image, falling back to a mimetype icon if the image is null.
+ */
+ private void showImage(DocumentInfo info, @Nullable Bitmap thumbnail) {
+ if (thumbnail != null) {
+ mThumbnail.resetPaddingToInitialValues();
+ mThumbnail.setScaleType(ScaleType.CENTER_CROP);
+ mThumbnail.setImageBitmap(thumbnail);
+ } else {
+ mThumbnail.setPadding(0, 0, 0, mTitle.getHeight());
+
+ Drawable mimeIcon =
+ mContext.getContentResolver().getTypeDrawable(info.mimeType);
+ mThumbnail.setScaleType(ScaleType.FIT_CENTER);
+ mThumbnail.setImageDrawable(mimeIcon);
+ }
+ mThumbnail.animate().alpha(1.0f).start();
}
}
\ No newline at end of file
diff --git a/src/com/android/documentsui/inspector/InspectorActivity.java b/src/com/android/documentsui/inspector/InspectorActivity.java
index 44af735..d02c43b 100644
--- a/src/com/android/documentsui/inspector/InspectorActivity.java
+++ b/src/com/android/documentsui/inspector/InspectorActivity.java
@@ -33,7 +33,7 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
- setContentView(R.layout.document_inspector_activity);
+ setContentView(R.layout.inspector_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setActionBar(toolbar);
@@ -45,10 +45,7 @@
if (mFragment == null) {
Intent intent = getIntent();
-
mFragment = InspectorFragment.newInstance(intent);
-
-
fragmentManager.beginTransaction()
.add(R.id.fragment_container, mFragment)
.commit();
diff --git a/src/com/android/documentsui/inspector/InspectorController.java b/src/com/android/documentsui/inspector/InspectorController.java
index 2b1c4b4..79612f9 100644
--- a/src/com/android/documentsui/inspector/InspectorController.java
+++ b/src/com/android/documentsui/inspector/InspectorController.java
@@ -15,59 +15,69 @@
*/
package com.android.documentsui.inspector;
-import static android.provider.DocumentsContract.Document.FLAG_SUPPORTS_SETTINGS;
import static com.android.internal.util.Preconditions.checkArgument;
+import android.annotation.StringRes;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
import android.provider.DocumentsContract;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.view.View;
import android.view.View.OnClickListener;
+
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.ProviderExecutor;
import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.base.Lookup;
+import com.android.documentsui.base.Shared;
import com.android.documentsui.inspector.actions.Action;
import com.android.documentsui.inspector.actions.ClearDefaultAppAction;
import com.android.documentsui.inspector.actions.ShowInProviderAction;
import com.android.documentsui.roots.ProvidersAccess;
import com.android.documentsui.ui.Snackbars;
-import java.util.concurrent.Executor;
+
import java.util.function.Consumer;
/**
* A controller that coordinates retrieving document information and sending it to the view.
*/
public final class InspectorController {
- private final Loader mLoader;
- private final Consumer<DocumentInfo> mHeader;
+ private final DataSupplier mLoader;
+ private final HeaderDisplay mHeader;
private final DetailsDisplay mDetails;
+ private final MediaDisplay mMedia;
private final ActionDisplay mShowProvider;
private final ActionDisplay mAppDefaults;
- private final Consumer<DocumentInfo> mDebugView;
- private final boolean mShowDebug;
+ private final DebugDisplay mDebugView;
private final Context mContext;
private final PackageManager mPackageManager;
private final ProvidersAccess mProviders;
- private final Runnable mShowSnackbar;
- private final Lookup<String, Executor> mExecutors;
+ private final Runnable mErrorSnackbar;
+ private Bundle mArgs;
/**
* InspectorControllerTest relies on this controller.
*/
@VisibleForTesting
- public InspectorController(Context context, Loader loader, PackageManager pm,
- ProvidersAccess providers, boolean showDebug, Consumer<DocumentInfo> header,
- DetailsDisplay details, ActionDisplay showProvider, ActionDisplay appDefaults,
- Consumer<DocumentInfo> debugView, Lookup<String, Executor> executors,
- Runnable showSnackbar) {
+ public InspectorController(
+ Context context,
+ DataSupplier loader,
+ PackageManager pm,
+ ProvidersAccess providers,
+ HeaderDisplay header,
+ DetailsDisplay details,
+ MediaDisplay media,
+ ActionDisplay showProvider,
+ ActionDisplay appDefaults,
+ DebugDisplay debugView,
+ Bundle args,
+ Runnable errorRunnable) {
checkArgument(context != null);
checkArgument(loader != null);
@@ -75,46 +85,57 @@
checkArgument(providers != null);
checkArgument(header != null);
checkArgument(details != null);
+ checkArgument(media != null);
checkArgument(showProvider != null);
checkArgument(appDefaults != null);
checkArgument(debugView != null);
- checkArgument(showSnackbar != null);
- checkArgument(executors != null);
+ checkArgument(args != null);
+ checkArgument(errorRunnable != null);
mContext = context;
mLoader = loader;
mPackageManager = pm;
- mShowDebug = showDebug;
mProviders = providers;
mHeader = header;
mDetails = details;
+ mMedia = media;
mShowProvider = showProvider;
mAppDefaults = appDefaults;
+ mArgs = args;
mDebugView = debugView;
- mExecutors = executors;
- mShowSnackbar = showSnackbar;
+
+ mErrorSnackbar = errorRunnable;
}
- public InspectorController(Activity activity, Loader loader, View layout, boolean showDebug) {
-
+ /**
+ * @param activity
+ * @param loader
+ * @param layout
+ * @param args Bundle of arguments passed to our host {@link InspectorFragment}. These
+ * can include extras that enable debug mode ({@link Shared#EXTRA_SHOW_DEBUG}
+ * and override the file title (@link {@link Intent#EXTRA_TITLE}).
+ */
+ public InspectorController(Activity activity, DataSupplier loader, View layout, Bundle args) {
this(activity,
- loader,
- activity.getPackageManager(),
- DocumentsApplication.getProvidersCache (activity),
- showDebug,
- (HeaderView) layout.findViewById(R.id.inspector_header_view),
- (DetailsView) layout.findViewById(R.id.inspector_details_view),
- (ActionDisplay) layout.findViewById(R.id.inspector_show_in_provider_view),
- (ActionDisplay) layout.findViewById(R.id.inspector_app_defaults_view),
- (DebugView) layout.findViewById(R.id.inspector_debug_view),
- ProviderExecutor::forAuthority,
- () -> {
- // using a runnable to support unit testing this feature.
- Snackbars.showInspectorError(activity);
- }
+ loader,
+ activity.getPackageManager(),
+ DocumentsApplication.getProvidersCache (activity),
+ (HeaderView) layout.findViewById(R.id.inspector_header_view),
+ (DetailsView) layout.findViewById(R.id.inspector_details_view),
+ (MediaView) layout.findViewById(R.id.inspector_media_view),
+ (ActionDisplay) layout.findViewById(R.id.inspector_show_in_provider_view),
+ (ActionDisplay) layout.findViewById(R.id.inspector_app_defaults_view),
+ (DebugView) layout.findViewById(R.id.inspector_debug_view),
+ args,
+ () -> {
+ // using a runnable to support unit testing this feature.
+ Snackbars.showInspectorError(activity);
+ }
);
- if (showDebug) {
- layout.findViewById(R.id.inspector_debug_view).setVisibility(View.VISIBLE);
+
+ if (args.getBoolean(Shared.EXTRA_SHOW_DEBUG)) {
+ DebugView view = (DebugView) layout.findViewById(R.id.inspector_debug_view);
+ view.init(ProviderExecutor::forAuthority);
}
}
@@ -129,13 +150,11 @@
/**
* Updates the view with documentInfo.
*/
- @Nullable
- public void updateView(@Nullable DocumentInfo docInfo) {
-
+ private void updateView(@Nullable DocumentInfo docInfo) {
if (docInfo == null) {
- mShowSnackbar.run();
+ mErrorSnackbar.run();
} else {
- mHeader.accept(docInfo);
+ mHeader.accept(docInfo, mArgs.getString(Intent.EXTRA_TITLE, docInfo.displayName));
mDetails.accept(docInfo);
if (docInfo.isDirectory()) {
@@ -147,28 +166,62 @@
Action showProviderAction =
new ShowInProviderAction(mContext, mPackageManager, docInfo, mProviders);
mShowProvider.init(
- showProviderAction,
- (view) -> {
- showInProvider(docInfo.derivedUri);
- });
+ showProviderAction,
+ (view) -> {
+ showInProvider(docInfo.derivedUri);
+ });
}
Action defaultAction =
- new ClearDefaultAppAction(mContext, mPackageManager, docInfo);
+ new ClearDefaultAppAction(mContext, mPackageManager, docInfo);
mAppDefaults.setVisible(defaultAction.canPerformAction());
if (defaultAction.canPerformAction()) {
mAppDefaults.init(
- defaultAction,
- (View) -> {
- clearDefaultApp(defaultAction.getPackageName());
- });
+ defaultAction,
+ (View) -> {
+ clearDefaultApp(defaultAction.getPackageName());
+ });
}
}
- if (mShowDebug) {
+ if (docInfo.isMetadataSupported()) {
+ mLoader.getDocumentMetadata(
+ docInfo.derivedUri,
+ (Bundle bundle) -> {
+ onDocumentMetadataLoaded(docInfo, bundle);
+ });
+ }
+ mMedia.setVisible(!mMedia.isEmpty());
+
+ if (mArgs.getBoolean(Shared.EXTRA_SHOW_DEBUG)) {
mDebugView.accept(docInfo);
}
+ mDebugView.setVisible(mArgs.getBoolean(Shared.EXTRA_SHOW_DEBUG)
+ && !mDebugView.isEmpty());
+ }
+ }
+
+ private void onDocumentMetadataLoaded(DocumentInfo doc, @Nullable Bundle metadata) {
+ if (metadata == null) {
+ return;
+ }
+
+ Runnable geoClickListener = null;
+ if (MetadataUtils.hasGeoCoordinates(metadata)) {
+ float[] coords = MetadataUtils.getGeoCoordinates(metadata);
+ final Intent intent = createGeoIntent(coords[0], coords[1], doc.displayName);
+ if (hasHandler(intent)) {
+ geoClickListener = () -> {
+ startActivity(intent);
+ };
+ }
+ }
+
+ mMedia.accept(doc, metadata, geoClickListener);
+
+ if (mArgs.getBoolean(Shared.EXTRA_SHOW_DEBUG)) {
+ mDebugView.accept(metadata);
}
}
@@ -181,6 +234,31 @@
mDetails.setChildrenCount(count);
}
+ private void startActivity(Intent intent) {
+ assert hasHandler(intent);
+ mContext.startActivity(intent);
+ }
+
+ /**
+ * checks that we can handle a geo-intent.
+ */
+ private boolean hasHandler(Intent intent) {
+ return mPackageManager.resolveActivity(intent, 0) != null;
+ }
+
+ /**
+ * Creates a geo-intent for opening a location in maps.
+ *
+ * @see https://developer.android.com/guide/components/intents-common.html#Maps
+ */
+ private static Intent createGeoIntent(
+ float latitude, float longitude, @Nullable String label) {
+ label = Uri.encode(label == null ? "" : label);
+ String data = "geo:0,0?q=" + latitude + " " + longitude + "(" + label + ")";
+ Uri uri = Uri.parse(data);
+ return new Intent(Intent.ACTION_VIEW, uri);
+ }
+
/**
* Shows the selected document in it's content provider.
*
@@ -210,9 +288,10 @@
}
/**
- * Interface for loading document metadata.
+ * Interface for loading all the various forms of document data. This primarily
+ * allows us to easily supply test data in tests.
*/
- public interface Loader {
+ public interface DataSupplier {
/**
* Starts the Asynchronous process of loading file data.
@@ -235,12 +314,28 @@
* Deletes all loader id's when android lifecycle ends.
*/
void reset();
+
+ /**
+ * @param uri
+ * @param callback
+ */
+ void getDocumentMetadata(Uri uri, Consumer<Bundle> callback);
}
/**
* This interface is for unit testing.
*/
- public interface ActionDisplay {
+ public interface Display {
+ /**
+ * Makes the action visible.
+ */
+ void setVisible(boolean visible);
+ }
+
+ /**
+ * This interface is for unit testing.
+ */
+ public interface ActionDisplay extends Display {
/**
* Initializes the view based on the action.
@@ -249,11 +344,6 @@
*/
void init(Action action, OnClickListener listener);
- /**
- * Makes the action visible.
- */
- void setVisible(boolean visible);
-
void setActionHeader(String header);
void setAppIcon(Drawable icon);
@@ -266,10 +356,63 @@
/**
* Provides details about a file.
*/
+ public interface HeaderDisplay {
+ void accept(DocumentInfo info, String displayName);
+ }
+
+ /**
+ * Provides basic details about a file.
+ */
public interface DetailsDisplay {
void accept(DocumentInfo info);
void setChildrenCount(int count);
}
+
+ /**
+ * Provides details about a media file.
+ */
+ public interface MediaDisplay extends Display {
+ void accept(DocumentInfo info, Bundle metadata, @Nullable Runnable geoClickListener);
+
+ /**
+ * Returns true if there are now rows in the display. Does not consider the title.
+ */
+ boolean isEmpty();
+ }
+
+ /**
+ * Provides details about a media file.
+ */
+ public interface DebugDisplay extends Display {
+ void accept(DocumentInfo info);
+ void accept(Bundle metadata);
+
+ /**
+ * Returns true if there are now rows in the display. Does not consider the title.
+ */
+ boolean isEmpty();
+ }
+
+ /**
+ * Displays a table of image metadata.
+ */
+ public interface TableDisplay extends Display {
+
+ /**
+ * Adds a row in the table.
+ */
+ void put(@StringRes int keyId, CharSequence value);
+
+ /**
+ * Adds a row in the table and makes it clickable.
+ */
+ void put(@StringRes int keyId, CharSequence value, OnClickListener callback);
+
+ /**
+ * Returns true if there are now rows in the display. Does not consider the title.
+ */
+ boolean isEmpty();
+ }
}
\ No newline at end of file
diff --git a/src/com/android/documentsui/inspector/InspectorFragment.java b/src/com/android/documentsui/inspector/InspectorFragment.java
index ef7c3b1..b2fd155 100644
--- a/src/com/android/documentsui/inspector/InspectorFragment.java
+++ b/src/com/android/documentsui/inspector/InspectorFragment.java
@@ -27,8 +27,7 @@
import android.widget.ScrollView;
import com.android.documentsui.R;
-import com.android.documentsui.base.Shared;
-import com.android.documentsui.inspector.InspectorController.Loader;
+import com.android.documentsui.inspector.InspectorController.DataSupplier;
/**
* Displays the Properties view in Files.
@@ -47,12 +46,11 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- final Loader loader = new DocumentLoader(getActivity(), getLoaderManager());
+ final DataSupplier loader = new RuntimeDataSupplier(getActivity(), getLoaderManager());
- mView = (ScrollView) inflater.inflate(R.layout.document_inspector_fragment,
+ mView = (ScrollView) inflater.inflate(R.layout.inspector_fragment,
container, false);
- boolean showDebug = (boolean) getArguments().get(Shared.EXTRA_SHOW_DEBUG);
- mController = new InspectorController(getActivity(), loader, mView, showDebug);
+ mController = new InspectorController(getActivity(), loader, mView, getArguments());
return mView;
}
@@ -70,16 +68,17 @@
}
/**
- * Creates a fragment and sets a Uri as an argument.
+ * Creates a fragment with the appropriate args.
*/
public static InspectorFragment newInstance(Intent intent) {
- Uri uri = intent.getData();
- boolean showDebug = intent.getBooleanExtra(Shared.EXTRA_SHOW_DEBUG, false);
+ Bundle extras = intent.getExtras();
+ extras = extras != null ? extras : Bundle.EMPTY;
+ Bundle args = extras.deepCopy();
+
+ Uri uri = intent.getData();
checkArgument(uri.getScheme().equals("content"));
- Bundle args = new Bundle();
args.putParcelable(DOC_URI_ARG, uri);
- args.putBoolean(Shared.EXTRA_SHOW_DEBUG, showDebug);
InspectorFragment fragment = new InspectorFragment();
fragment.setArguments(args);
diff --git a/src/com/android/documentsui/inspector/KeyValueRow.java b/src/com/android/documentsui/inspector/KeyValueRow.java
index 45a6e05..48801d5 100644
--- a/src/com/android/documentsui/inspector/KeyValueRow.java
+++ b/src/com/android/documentsui/inspector/KeyValueRow.java
@@ -15,12 +15,17 @@
*/
package com.android.documentsui.inspector;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.StringRes;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
+import android.graphics.Paint;
+import android.support.annotation.Nullable;
+import android.text.Selection;
+import android.text.Spannable;
import android.util.AttributeSet;
+import android.view.View;
+import android.view.textclassifier.TextClassifier;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -32,6 +37,8 @@
public class KeyValueRow extends LinearLayout {
private final Resources mRes;
+ private @Nullable ColorStateList mDefaultTextColor;
+ private @Nullable TextClassifier mClassifier;
public KeyValueRow(Context context) {
this(context, null);
@@ -43,15 +50,18 @@
public KeyValueRow(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
-
mRes = context.getResources();
}
+ public void setTextClassifier(TextClassifier classifier) {
+ mClassifier = classifier;
+ }
+
/**
* Sets the raw value of the key. Only localized values
* should be passed.
*/
- public void setKey(String key) {
+ public void setKey(CharSequence key) {
((TextView) findViewById(R.id.table_row_key)).setText(key);
}
@@ -59,7 +69,38 @@
setKey(mRes.getString(id));
}
- public void setValue(String value) {
- ((TextView) findViewById(R.id.table_row_value)).setText(value);
+ public void setValue(CharSequence value) {
+ TextView text = ((TextView) findViewById(R.id.table_row_value));
+ text.setText(value);
+ text.setTextClassifier(mClassifier);
+ text.setOnLongClickListener((View view) -> {
+
+ CharSequence textValue = text.getText();
+ if (textValue instanceof Spannable) {
+ Spannable spn = (Spannable) textValue;
+ Selection.selectAll(spn);
+ }
+ // we still want the default selection arrows and menu after we specified to select
+ // all text in the TextView.
+ return false;
+ });
+ }
+
+ @Override
+ public void setOnClickListener(OnClickListener callback) {
+ TextView clickable = ((TextView) findViewById(R.id.table_row_value));
+ mDefaultTextColor = clickable.getTextColors();
+ clickable.setTextColor(R.color.inspector_link);
+ clickable.setPaintFlags(clickable.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ clickable.setOnClickListener(callback);
+ }
+
+ public void removeOnClickListener() {
+ TextView reset = ((TextView) findViewById(R.id.table_row_value));
+ if (mDefaultTextColor != null) {
+ reset.setTextColor(mDefaultTextColor);
+ }
+ reset.setPaintFlags(reset.getPaintFlags() & ~Paint.UNDERLINE_TEXT_FLAG);
+ reset.setOnClickListener(null);
}
}
diff --git a/src/com/android/documentsui/inspector/MediaView.java b/src/com/android/documentsui/inspector/MediaView.java
new file mode 100644
index 0000000..b2ae758
--- /dev/null
+++ b/src/com/android/documentsui/inspector/MediaView.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.location.Address;
+import android.location.Geocoder;
+import android.media.ExifInterface;
+import android.media.MediaMetadata;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.support.annotation.VisibleForTesting;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+
+import com.android.documentsui.R;
+import com.android.documentsui.base.DocumentInfo;
+import com.android.documentsui.base.Shared;
+import com.android.documentsui.inspector.InspectorController.MediaDisplay;
+import com.android.documentsui.inspector.InspectorController.TableDisplay;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import javax.annotation.Nullable;
+
+/**
+ * Organizes and Displays the debug information about a file. This view
+ * should only be made visible when build is debuggable and system policies
+ * allow debug "stuff".
+ */
+public class MediaView extends TableView implements MediaDisplay {
+
+ private final Resources mResources;
+ private final Context mContext;
+
+ public MediaView(Context context) {
+ this(context, null);
+ }
+
+ public MediaView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public MediaView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mContext = context;
+ mResources = context.getResources();
+ }
+
+ @Override
+ public void accept(DocumentInfo doc, Bundle metadata, @Nullable Runnable geoClickListener) {
+ setTitle(R.string.inspector_metadata_section, true);
+
+ Bundle exif = metadata.getBundle(DocumentsContract.METADATA_EXIF);
+ if (exif != null) {
+ showExifData(this, mResources, doc, exif, geoClickListener, this::getAddress);
+ }
+
+ Bundle video = metadata.getBundle(Shared.METADATA_KEY_VIDEO);
+ if (video != null) {
+ showVideoData(this, mResources, doc, video, geoClickListener);
+ }
+
+ Bundle audio = metadata.getBundle(Shared.METADATA_KEY_AUDIO);
+ if (audio != null) {
+ showAudioData(this, audio);
+ }
+
+ setVisible(!isEmpty());
+ }
+
+ @VisibleForTesting
+ public static void showAudioData(TableDisplay table, Bundle tags) {
+
+ if (tags.containsKey(MediaMetadata.METADATA_KEY_ARTIST)) {
+ table.put(R.string.metadata_artist, tags.getString(MediaMetadata.METADATA_KEY_ARTIST));
+ }
+
+ if (tags.containsKey(MediaMetadata.METADATA_KEY_COMPOSER)) {
+ table.put(R.string.metadata_composer,
+ tags.getString(MediaMetadata.METADATA_KEY_COMPOSER));
+ }
+
+ if (tags.containsKey(MediaMetadata.METADATA_KEY_ALBUM)) {
+ table.put(R.string.metadata_album, tags.getString(MediaMetadata.METADATA_KEY_ALBUM));
+ }
+
+ if (tags.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
+ int millis = tags.getInt(MediaMetadata.METADATA_KEY_DURATION);
+ table.put(R.string.metadata_duration, DateUtils.formatElapsedTime(millis / 1000));
+ }
+ }
+
+ @VisibleForTesting
+ public static void showVideoData(
+ TableDisplay table,
+ Resources resources,
+ DocumentInfo doc,
+ Bundle tags,
+ @Nullable Runnable geoClickListener) {
+
+ addDimensionsRow(table, resources, tags);
+
+ if (MetadataUtils.hasVideoCoordinates(tags)) {
+ float[] coords = MetadataUtils.getVideoCoords(tags);
+ showCoordiantes(table, resources, coords, geoClickListener);
+ }
+
+ if (tags.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
+ int millis = tags.getInt(MediaMetadata.METADATA_KEY_DURATION);
+ table.put(R.string.metadata_duration, DateUtils.formatElapsedTime(millis / 1000));
+ }
+ }
+
+ @VisibleForTesting
+ public static void showExifData(
+ TableDisplay table,
+ Resources resources,
+ DocumentInfo doc,
+ Bundle tags,
+ @Nullable Runnable geoClickListener,
+ Consumer<float[]> geoAddressFetcher) {
+
+ addDimensionsRow(table, resources, tags);
+
+ if (tags.containsKey(ExifInterface.TAG_DATETIME)) {
+ String date = tags.getString(ExifInterface.TAG_DATETIME);
+ table.put(R.string.metadata_date_time, date);
+ }
+
+ if (tags.containsKey(ExifInterface.TAG_GPS_ALTITUDE)) {
+ double altitude = tags.getDouble(ExifInterface.TAG_GPS_ALTITUDE);
+ table.put(R.string.metadata_altitude, String.valueOf(altitude));
+ }
+
+ if (tags.containsKey(ExifInterface.TAG_MAKE) || tags.containsKey(ExifInterface.TAG_MODEL)) {
+ String make = tags.getString(ExifInterface.TAG_MAKE);
+ String model = tags.getString(ExifInterface.TAG_MODEL);
+ make = make != null ? make : "";
+ model = model != null ? model : "";
+ table.put(
+ R.string.metadata_camera,
+ resources.getString(R.string.metadata_camera_format, make, model));
+ }
+
+ if (tags.containsKey(ExifInterface.TAG_APERTURE)) {
+ table.put(R.string.metadata_aperture, resources.getString(
+ R.string.metadata_aperture_format, tags.getDouble(ExifInterface.TAG_APERTURE)));
+ }
+
+ if (tags.containsKey(ExifInterface.TAG_SHUTTER_SPEED_VALUE)) {
+ String shutterSpeed = String.valueOf(
+ formatShutterSpeed(tags.getDouble(ExifInterface.TAG_SHUTTER_SPEED_VALUE)));
+ table.put(R.string.metadata_shutter_speed, shutterSpeed);
+ }
+
+ if (tags.containsKey(ExifInterface.TAG_FOCAL_LENGTH)) {
+ double length = tags.getDouble(ExifInterface.TAG_FOCAL_LENGTH);
+ table.put(R.string.metadata_focal_length,
+ String.format(resources.getString(R.string.metadata_focal_format), length));
+ }
+
+ if (tags.containsKey(ExifInterface.TAG_ISO_SPEED_RATINGS)) {
+ int iso = tags.getInt(ExifInterface.TAG_ISO_SPEED_RATINGS);
+ table.put(R.string.metadata_iso_speed_ratings,
+ String.format(resources.getString(R.string.metadata_iso_format), iso));
+ }
+
+ if (MetadataUtils.hasExifGpsFields(tags)) {
+ float[] coords = MetadataUtils.getExifGpsCoords(tags);
+ showCoordiantes(table, resources, coords, geoClickListener);
+ geoAddressFetcher.accept(coords);
+ }
+ }
+
+ private static void showCoordiantes(
+ TableDisplay table,
+ Resources resources,
+ float[] coords,
+ @Nullable Runnable geoClickListener) {
+
+ String value = resources.getString(
+ R.string.metadata_coordinates_format, coords[0], coords[1]);
+ if (geoClickListener != null) {
+ table.put(
+ R.string.metadata_coordinates,
+ value,
+ view -> {
+ geoClickListener.run();
+ }
+ );
+ } else {
+ table.put(R.string.metadata_coordinates, value);
+ }
+ }
+
+ /**
+ * Attempts to retrieve an approximate address and displays the address if it can find one.
+ * @param coords the coordinates that gets an address.
+ */
+ private void getAddress(float[] coords) {
+ new AsyncTask<Float, Void, Address>() {
+ @Override
+ protected Address doInBackground(Float... coords) {
+ assert (coords.length == 2);
+ Geocoder geocoder = new Geocoder(mContext);
+ try {
+ Address address = geocoder.getFromLocation(coords[0], // latitude
+ coords[1], // longitude
+ 1 // amount of results returned
+ ).get(0);
+ return address;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ @Override
+ protected void onPostExecute(@Nullable Address address) {
+ if (address != null) {
+ TableDisplay table = MediaView.this;
+ if (address.getMaxAddressLineIndex() >= 0) {
+ String formattedAddress;
+ StringBuilder addressBuilder = new StringBuilder("");
+ addressBuilder.append(address.getAddressLine(0));
+ for (int i = 1; i < address.getMaxAddressLineIndex(); i++) {
+ addressBuilder.append("\n");
+ addressBuilder.append(address.getAddressLine(i));
+ }
+ formattedAddress = addressBuilder.toString();
+ table.put(R.string.metadata_address, formattedAddress);
+ } else if (address.getLocality() != null) {
+ table.put(R.string.metadata_address, address.getLocality());
+ } else if (address.getSubAdminArea() != null) {
+ table.put(R.string.metadata_address, address.getSubAdminArea());
+ } else if (address.getAdminArea() != null) {
+ table.put(R.string.metadata_address, address.getAdminArea());
+ } else if (address.getCountryName() != null) {
+ table.put(R.string.metadata_address, address.getCountryName());
+ } }
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, coords[0], coords[1]);
+ }
+
+ /**
+ * @param speed a value n, where shutter speed equals 1/(2^n)
+ * @return a String containing either a fraction that displays 1 over a positive integer, or a
+ * double rounded to one decimal, depending on if 1/(2^n) is less than or greater than 1,
+ * respectively.
+ */
+ private static String formatShutterSpeed(double speed) {
+ if (speed <= 0) {
+ double shutterSpeed = Math.pow(2, -1 * speed);
+ String formattedSpeed = String.valueOf(Math.round(shutterSpeed * 10.0) / 10.0);
+ return formattedSpeed;
+ } else {
+ int approximateSpeedDenom = (int) Math.pow(2, speed) + 1;
+ String formattedSpeed = "1/" + String.valueOf(approximateSpeedDenom);
+ return formattedSpeed;
+ }
+ }
+
+ /**
+ * @param table
+ * @param resources
+ * @param tags
+ */
+ private static void addDimensionsRow(TableDisplay table, Resources resources, Bundle tags) {
+ if (tags.containsKey(ExifInterface.TAG_IMAGE_WIDTH)
+ && tags.containsKey(ExifInterface.TAG_IMAGE_LENGTH)) {
+ int width = tags.getInt(ExifInterface.TAG_IMAGE_WIDTH);
+ int height = tags.getInt(ExifInterface.TAG_IMAGE_LENGTH);
+ float megaPixels = height * width / 1000000f;
+ table.put(R.string.metadata_dimensions,
+ resources.getString(
+ R.string.metadata_dimensions_format, width, height, megaPixels));
+ }
+ }
+}
diff --git a/src/com/android/documentsui/inspector/MetadataLoader.java b/src/com/android/documentsui/inspector/MetadataLoader.java
new file mode 100644
index 0000000..3de15ba
--- /dev/null
+++ b/src/com/android/documentsui/inspector/MetadataLoader.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import java.io.FileNotFoundException;
+
+/**
+ * Loads metadata from {@link DocumentsContract#getDocumentMetadata(android.content.ContentProviderClient, Uri, String[])}
+ */
+final class MetadataLoader extends AsyncTaskLoader<Bundle> {
+
+ private static final String TAG = "MetadataLoader";
+
+ private final Context mContext;
+ private final Uri mUri;
+
+ private @Nullable Bundle mMetadata;
+
+ MetadataLoader(Context context, Uri uri) {
+ super(context);
+ mContext = context;
+ mUri = uri;
+ }
+
+ @Override
+ public Bundle loadInBackground() {
+ try {
+ return DocumentsContract.getDocumentMetadata(mContext.getContentResolver(), mUri);
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Failed to load metadata for doc: " + mUri, e);
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onStartLoading() {
+ if (mMetadata != null) {
+ deliverResult(mMetadata);
+ }
+ if (takeContentChanged() || mMetadata == null) {
+ forceLoad();
+ }
+ }
+
+ @Override
+ public void deliverResult(Bundle metadata) {
+ if (isReset()) {
+ return;
+ }
+ mMetadata = metadata;
+ if (isStarted()) {
+ super.deliverResult(metadata);
+ }
+ }
+
+ /**
+ * Must be called from the UI thread
+ */
+ @Override
+ protected void onStopLoading() {
+ // Attempt to cancel the current load task if possible.
+ cancelLoad();
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+
+ // Ensure the loader is stopped
+ onStopLoading();
+
+ mMetadata = null;
+ }
+}
diff --git a/src/com/android/documentsui/inspector/MetadataUtils.java b/src/com/android/documentsui/inspector/MetadataUtils.java
new file mode 100644
index 0000000..b5c1034
--- /dev/null
+++ b/src/com/android/documentsui/inspector/MetadataUtils.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.media.ExifInterface;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+
+import com.android.documentsui.base.Shared;
+
+import javax.annotation.Nullable;
+
+final class MetadataUtils {
+
+ private MetadataUtils() {}
+
+ static boolean hasGeoCoordinates(@Nullable Bundle metadata) {
+ if (metadata == null) {
+ return false;
+ }
+ return hasVideoCoordinates(metadata.getBundle(Shared.METADATA_KEY_VIDEO))
+ || hasExifGpsFields(metadata.getBundle(DocumentsContract.METADATA_EXIF));
+ }
+
+ static boolean hasVideoCoordinates(@Nullable Bundle data) {
+ return data != null && (data.containsKey(Shared.METADATA_VIDEO_LATITUDE)
+ && data.containsKey(Shared.METADATA_VIDEO_LONGITUTE));
+ }
+
+ static boolean hasExifGpsFields(@Nullable Bundle exif) {
+ return exif != null && (exif.containsKey(ExifInterface.TAG_GPS_LATITUDE)
+ && exif.containsKey(ExifInterface.TAG_GPS_LONGITUDE)
+ && exif.containsKey(ExifInterface.TAG_GPS_LATITUDE_REF)
+ && exif.containsKey(ExifInterface.TAG_GPS_LONGITUDE_REF));
+ }
+
+ static float[] getGeoCoordinates(Bundle metadata) {
+ assert hasGeoCoordinates(metadata);
+ checkNotNull(metadata);
+
+ Bundle bundle = metadata.getBundle(DocumentsContract.METADATA_EXIF);
+ if (hasExifGpsFields(bundle)) {
+ return getExifGpsCoords(bundle);
+ }
+
+ bundle = metadata.getBundle(Shared.METADATA_KEY_VIDEO);
+ if (hasVideoCoordinates(bundle)) {
+ return getVideoCoords(bundle);
+ }
+
+ // This should never happen, because callers should always check w/ hasGeoCoordinates first.
+ throw new IllegalArgumentException("Invalid metadata bundle: " + metadata);
+ }
+
+ static float[] getExifGpsCoords(Bundle exif) {
+ assert hasExifGpsFields(exif);
+
+ String lat = exif.getString(ExifInterface.TAG_GPS_LATITUDE);
+ String lon = exif.getString(ExifInterface.TAG_GPS_LONGITUDE);
+ String latRef = exif.getString(ExifInterface.TAG_GPS_LATITUDE_REF);
+ String lonRef = exif.getString(ExifInterface.TAG_GPS_LONGITUDE_REF);
+
+ return new float[] {
+ ExifInterface.convertRationalLatLonToFloat(lat, latRef),
+ ExifInterface.convertRationalLatLonToFloat(lon, lonRef)
+ };
+ }
+
+ static float[] getVideoCoords(Bundle data) {
+ assert hasVideoCoordinates(data);
+ return new float[] {
+ data.getFloat(Shared.METADATA_VIDEO_LATITUDE),
+ data.getFloat(Shared.METADATA_VIDEO_LONGITUTE)
+ };
+ }
+}
diff --git a/src/com/android/documentsui/inspector/DocumentLoader.java b/src/com/android/documentsui/inspector/RuntimeDataSupplier.java
similarity index 77%
rename from src/com/android/documentsui/inspector/DocumentLoader.java
rename to src/com/android/documentsui/inspector/RuntimeDataSupplier.java
index 9c92b1c..bb8998b 100644
--- a/src/com/android/documentsui/inspector/DocumentLoader.java
+++ b/src/com/android/documentsui/inspector/RuntimeDataSupplier.java
@@ -27,32 +27,35 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
-
import android.provider.DocumentsContract;
import android.support.annotation.Nullable;
+
import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.inspector.InspectorController.Loader;
+import com.android.documentsui.inspector.InspectorController.DataSupplier;
+
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
- * Asynchronously loads a document's metadata for the inspector.
+ * Asynchronously loads a document data for the inspector.
+ *
+ * <p>This loader is not a Loader! Its our own funky loader.
*/
-public class DocumentLoader implements Loader {
+public class RuntimeDataSupplier implements DataSupplier {
private final Context mContext;
- private final LoaderManager mLoader;
- private List<Integer> loaderIds;
+ private final LoaderManager mLoaderMgr;
+ private final List<Integer> loaderIds = new ArrayList<>();
private @Nullable Callbacks mDocCallbacks;
private @Nullable Callbacks mDirCallbacks;
+ private @Nullable LoaderCallbacks<Bundle> mMetadataCallbacks;
- public DocumentLoader(Context context, LoaderManager loader) {
+ public RuntimeDataSupplier(Context context, LoaderManager loaderMgr) {
checkArgument(context != null);
- checkArgument(loader != null);
+ checkArgument(loaderMgr != null);
mContext = context;
- mLoader = loader;
- loaderIds = new ArrayList<>();
+ mLoaderMgr = loaderMgr;
}
/**
@@ -63,14 +66,10 @@
//Check that we have correct Uri type and that the loader is not already created.
checkArgument(uri.getScheme().equals("content"));
- //get a new loader id.
- int loadId = getNextLoaderId();
- checkArgument(mLoader.getLoader(loadId) == null);
- loaderIds.add(loadId);
-
Consumer<Cursor> callback = new Consumer<Cursor>() {
@Override
public void accept(Cursor cursor) {
+
if (cursor == null || !cursor.moveToFirst()) {
updateView.accept(null);
} else {
@@ -81,7 +80,7 @@
};
mDocCallbacks = new Callbacks(mContext, uri, callback);
- mLoader.restartLoader(loadId, null, mDocCallbacks);
+ mLoaderMgr.restartLoader(getNextLoaderId(), null, mDocCallbacks);
}
/**
@@ -93,11 +92,6 @@
Uri children = DocumentsContract.buildChildDocumentsUri(
directory.authority, directory.documentId);
- //get a new loader id.
- int loadId = getNextLoaderId();
- checkArgument(mLoader.getLoader(loadId) == null);
- loaderIds.add(loadId);
-
Consumer<Cursor> callback = new Consumer<Cursor>() {
@Override
public void accept(Cursor cursor) {
@@ -108,19 +102,42 @@
};
mDirCallbacks = new Callbacks(mContext, children, callback);
- mLoader.restartLoader(loadId, null, mDirCallbacks);
+ mLoaderMgr.restartLoader(getNextLoaderId(), null, mDirCallbacks);
+ }
+
+ @Override
+ public void getDocumentMetadata(Uri uri, Consumer<Bundle> callback) {
+ mMetadataCallbacks = new LoaderCallbacks<Bundle>() {
+ @Override
+ public android.content.Loader<Bundle> onCreateLoader(int id, Bundle unused) {
+ return new MetadataLoader(mContext, uri);
+ }
+
+ @Override
+ public void onLoadFinished(android.content.Loader<Bundle> loader, Bundle data) {
+ callback.accept(data);
+ }
+
+ @Override
+ public void onLoaderReset(android.content.Loader<Bundle> loader) {
+ }
+ };
+
+ // TODO: Listen for changes on content URI.
+ mLoaderMgr.restartLoader(getNextLoaderId(), null, mMetadataCallbacks);
}
@Override
public void reset() {
for (Integer id : loaderIds) {
- mLoader.destroyLoader(id);
+ mLoaderMgr.destroyLoader(id);
}
loaderIds.clear();
if (mDocCallbacks != null && mDocCallbacks.getObserver() != null) {
mContext.getContentResolver().unregisterContentObserver(mDocCallbacks.getObserver());
}
+
if (mDirCallbacks != null && mDirCallbacks.getObserver() != null) {
mContext.getContentResolver().unregisterContentObserver(mDocCallbacks.getObserver());
}
@@ -128,10 +145,11 @@
private int getNextLoaderId() {
int id = 0;
- while(mLoader.getLoader(id) != null) {
+ while(mLoaderMgr.getLoader(id) != null) {
id++;
checkArgument(id <= Integer.MAX_VALUE);
}
+ loaderIds.add(id);
return id;
}
@@ -195,4 +213,4 @@
mContentChangedCallback.run();
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/documentsui/inspector/TableView.java b/src/com/android/documentsui/inspector/TableView.java
index 91c30d8..191e89a 100644
--- a/src/com/android/documentsui/inspector/TableView.java
+++ b/src/com/android/documentsui/inspector/TableView.java
@@ -20,28 +20,29 @@
import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.LayoutInflater;
+import android.view.View;
import android.view.ViewGroup;
+import android.view.textclassifier.TextClassifier;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.documentsui.R;
+import com.android.documentsui.inspector.InspectorController.TableDisplay;
import java.util.HashMap;
import java.util.Map;
-import javax.annotation.Nullable;
-
-
/**
* Organizes and Displays the basic details about a file
*/
-public class TableView extends LinearLayout {
+public class TableView extends LinearLayout implements TableDisplay {
private final LayoutInflater mInflater;
- private final Map<String, KeyValueRow> mRows = new HashMap<>();
+ private final Map<CharSequence, KeyValueRow> mRows = new HashMap<>();
private final Resources mRes;
- private @Nullable TextView mTitle;
+ private final Map<CharSequence, TextView> mTitles = new HashMap<>();
+ private final TextClassifier mClassifier;
public TableView(Context context) {
this(context, null);
@@ -55,40 +56,77 @@
super(context, attrs, defStyleAttr);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRes = context.getResources();
+ mClassifier = GpsCoordinatesTextClassifier.create(context);
}
- protected void setTitle(ViewGroup parent, @StringRes int title) {
- if (mTitle == null) {
- mTitle = (TextView) mInflater.inflate(R.layout.inspector_section_title, null);
- parent.addView(mTitle);
+ void setTitle(@StringRes int title, boolean showDivider) {
+ putTitle(mContext.getResources().getString(title), showDivider);
+ }
+
+ // A naughty title method (that takes strings, not message ids), mostly for DebugView.
+ protected void putTitle(CharSequence title, boolean showDivider) {
+ TextView view = mTitles.get(title);
+ if (view == null) {
+ LinearLayout layout =
+ (LinearLayout) mInflater.inflate(R.layout.inspector_section_title, null);
+ if (!showDivider) {
+ layout.setDividerDrawable(null);
+ }
+ view = (TextView) layout.findViewById(R.id.inspector_header_title);
+ addView(layout);
+ mTitles.put(title, view);
}
- mTitle.setText(mContext.getResources().getString(title));
+ view.setText(title);
}
protected KeyValueRow createKeyValueRow(ViewGroup parent) {
KeyValueRow row = (KeyValueRow) mInflater.inflate(R.layout.table_key_value_row, null);
parent.addView(row);
+ row.setTextClassifier(mClassifier);
return row;
}
/**
- * Puts or updates an value in the table view.
+ * Puts or updates a value in the table view.
*/
- protected void put(@StringRes int keyId, String value) {
+ @Override
+ public void put(@StringRes int keyId, CharSequence value) {
put(mRes.getString(keyId), value);
}
+
/**
- * Puts or updates an value in the table view.
+ * Puts or updates a value in the table view.
*/
- protected void put(String key, String value) {
- if(mRows.containsKey(key)) {
- mRows.get(key).setValue(value);
- } else {
- KeyValueRow row = createKeyValueRow(this);
+ protected KeyValueRow put(CharSequence key, CharSequence value) {
+ KeyValueRow row = mRows.get(key);
+
+ if (row == null) {
+ row = createKeyValueRow(this);
row.setKey(key);
- row.setValue(value);
mRows.put(key, row);
+ } else {
+ row.removeOnClickListener();
}
+
+ row.setValue(value);
+ row.setTextClassifier(mClassifier);
+ return row;
+ }
+
+ @Override
+ public void put(@StringRes int keyId, CharSequence value, OnClickListener callback) {
+ put(keyId, value);
+ mRows.get(mRes.getString(keyId)).setOnClickListener(callback);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mRows.isEmpty();
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
diff --git a/src/com/android/documentsui/inspector/actions/Action.java b/src/com/android/documentsui/inspector/actions/Action.java
index 1b0b693..d90d6dc 100644
--- a/src/com/android/documentsui/inspector/actions/Action.java
+++ b/src/com/android/documentsui/inspector/actions/Action.java
@@ -17,6 +17,7 @@
package com.android.documentsui.inspector.actions;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -54,6 +55,8 @@
public abstract @Nullable String getPackageName();
+ public abstract @StringRes int getButtonLabel();
+
public @Nullable Drawable getAppIcon() {
String packageName = getPackageName();
diff --git a/src/com/android/documentsui/inspector/actions/ActionView.java b/src/com/android/documentsui/inspector/actions/ActionView.java
index 485e2b1..b519bcc 100644
--- a/src/com/android/documentsui/inspector/actions/ActionView.java
+++ b/src/com/android/documentsui/inspector/actions/ActionView.java
@@ -15,6 +15,7 @@
*/
package com.android.documentsui.inspector.actions;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -34,6 +35,7 @@
*/
public final class ActionView extends LinearLayout implements InspectorController.ActionDisplay {
+ private Context mContext;
private final TextView mHeader;
private final ImageView mAppIcon;
private final TextView mAppName;
@@ -55,12 +57,18 @@
View view = inflater.inflate(R.layout.inspector_action_view, null);
addView(view);
- mHeader = (TextView) findViewById(R.id.action_header);
+ mContext = context;
+ mHeader = getSectionTitle();
mAppIcon = (ImageView) findViewById(R.id.app_icon);
mAppName = (TextView) findViewById(R.id.app_name);
mActionButton = (ImageButton) findViewById(R.id.inspector_action_button);
}
+ public TextView getSectionTitle() {
+ LinearLayout header = (LinearLayout) findViewById(R.id.action_header);
+ return (TextView) header.findViewById(R.id.inspector_header_title);
+ }
+
@Override
public void init(Action action, OnClickListener listener) {
mAction = action;
@@ -68,6 +76,7 @@
setAppIcon(mAction.getAppIcon());
setAppName(mAction.getAppName());
+ mActionButton.setContentDescription(mContext.getString(action.getButtonLabel()));
mActionButton.setOnClickListener(listener);
showAction(true);
@@ -84,8 +93,14 @@
}
@Override
- public void setAppIcon(Drawable icon) {
- mAppIcon.setImageDrawable(icon);
+ public void setAppIcon(@Nullable Drawable icon) {
+
+ if (icon != null) {
+ mAppIcon.setVisibility(View.VISIBLE);
+ mAppIcon.setImageDrawable(icon);
+ } else {
+ mAppIcon.setVisibility(View.GONE);
+ }
}
@Override
diff --git a/src/com/android/documentsui/inspector/actions/ClearDefaultAppAction.java b/src/com/android/documentsui/inspector/actions/ClearDefaultAppAction.java
index 4f954ba..f8f6aeb 100644
--- a/src/com/android/documentsui/inspector/actions/ClearDefaultAppAction.java
+++ b/src/com/android/documentsui/inspector/actions/ClearDefaultAppAction.java
@@ -15,6 +15,7 @@
*/
package com.android.documentsui.inspector.actions;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -84,4 +85,8 @@
return null;
}
}
+
+ public @StringRes int getButtonLabel() {
+ return R.string.button_clear;
+ }
}
\ No newline at end of file
diff --git a/src/com/android/documentsui/inspector/actions/ShowInProviderAction.java b/src/com/android/documentsui/inspector/actions/ShowInProviderAction.java
index aee649d..0dc221a 100644
--- a/src/com/android/documentsui/inspector/actions/ShowInProviderAction.java
+++ b/src/com/android/documentsui/inspector/actions/ShowInProviderAction.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
+import android.support.annotation.StringRes;
import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.roots.ProvidersAccess;
@@ -67,4 +68,8 @@
public String getPackageName() {
return mProviders.getPackageName(mDoc.derivedUri.getAuthority());
}
+
+ public @StringRes int getButtonLabel() {
+ return R.string.button_show_provider;
+ }
}
\ No newline at end of file
diff --git a/src/com/android/documentsui/picker/ActionHandler.java b/src/com/android/documentsui/picker/ActionHandler.java
index 0a3972a..596c627 100644
--- a/src/com/android/documentsui/picker/ActionHandler.java
+++ b/src/com/android/documentsui/picker/ActionHandler.java
@@ -41,6 +41,7 @@
import com.android.documentsui.DocumentsAccess;
import com.android.documentsui.Injector;
import com.android.documentsui.Metrics;
+import com.android.documentsui.Model;
import com.android.documentsui.base.BooleanConsumer;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
@@ -50,11 +51,10 @@
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.AnimationView;
-import com.android.documentsui.dirlist.DocumentDetails;
-import com.android.documentsui.Model;
import com.android.documentsui.picker.ActionHandler.Addons;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.roots.ProvidersAccess;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
import com.android.documentsui.services.FileOperationService;
import com.android.internal.annotations.VisibleForTesting;
@@ -246,12 +246,12 @@
}
@Override
- public boolean openDocument(DocumentDetails details, @ViewType int type,
+ public boolean openItem(ItemDetails details, @ViewType int type,
@ViewType int fallback) {
- DocumentInfo doc = mModel.getDocument(details.getModelId());
+ DocumentInfo doc = mModel.getDocument(details.getStableId());
if (doc == null) {
Log.w(TAG,
- "Can't view item. No Document available for modeId: " + details.getModelId());
+ "Can't view item. No Document available for modeId: " + details.getStableId());
return false;
}
@@ -374,6 +374,7 @@
}
public interface Addons extends CommonAddons {
+ @Override
void onDocumentPicked(DocumentInfo doc);
/**
diff --git a/src/com/android/documentsui/picker/PickActivity.java b/src/com/android/documentsui/picker/PickActivity.java
index fb43ce6..94327b1 100644
--- a/src/com/android/documentsui/picker/PickActivity.java
+++ b/src/com/android/documentsui/picker/PickActivity.java
@@ -34,6 +34,7 @@
import com.android.documentsui.ActionModeController;
import com.android.documentsui.BaseActivity;
+import com.android.documentsui.DocsSelectionHelper;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.FocusManager;
import com.android.documentsui.Injector;
@@ -49,7 +50,6 @@
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.prefs.ScopedPreferences;
-import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.sidebar.RootsFragment;
import com.android.documentsui.ui.DialogController;
@@ -94,10 +94,9 @@
super.onCreate(icicle);
- mInjector.selectionMgr = new SelectionManager(
- mState.allowMultiple
- ? SelectionManager.MODE_MULTIPLE
- : SelectionManager.MODE_SINGLE);
+ mInjector.selectionMgr = mState.allowMultiple
+ ? DocsSelectionHelper.createMultiSelect()
+ : DocsSelectionHelper.createSingleSelect();
mInjector.focusManager = new FocusManager(
mInjector.features,
diff --git a/src/com/android/documentsui/prefs/LocalPreferences.java b/src/com/android/documentsui/prefs/LocalPreferences.java
index 48a9220..955b19d 100644
--- a/src/com/android/documentsui/prefs/LocalPreferences.java
+++ b/src/com/android/documentsui/prefs/LocalPreferences.java
@@ -19,20 +19,19 @@
import static com.android.documentsui.base.State.MODE_UNKNOWN;
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.os.UserHandle;
import android.preference.PreferenceManager;
import com.android.documentsui.base.RootInfo;
-import com.android.documentsui.base.State;
import com.android.documentsui.base.State.ViewMode;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+/**
+ * Methods for accessing the local preferences.
+ */
public class LocalPreferences {
private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
@@ -66,64 +65,6 @@
@Retention(RetentionPolicy.SOURCE)
public @interface PermissionStatus {}
- /**
- * Clears all preferences associated with a given package.
- *
- * <p>Typically called when a package is removed or when user asked to clear its data.
- */
- public static void clearPackagePreferences(Context context, String packageName) {
- clearScopedAccessPreferences(context, packageName);
- }
-
- /**
- * Methods below are used to keep track of denied user requests on scoped directory access so
- * the dialog is not offered when user checked the 'Do not ask again' box
- *
- * <p>It uses a shared preferences, whose key is:
- * <ol>
- * <li>{@code USER_ID|PACKAGE_NAME|VOLUME_UUID|DIRECTORY} for storage volumes that have a UUID
- * (typically physical volumes like SD cards).
- * <li>{@code USER_ID|PACKAGE_NAME||DIRECTORY} for storage volumes that do not have a UUID
- * (typically the emulated volume used for primary storage
- * </ol>
- */
- public static @PermissionStatus int getScopedAccessPermissionStatus(Context context,
- String packageName, @Nullable String uuid, String directory) {
- final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
- return getPrefs(context).getInt(key, PERMISSION_ASK);
- }
-
- public static void setScopedAccessPermissionStatus(Context context, String packageName,
- @Nullable String uuid, String directory, @PermissionStatus int status) {
- final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
- getPrefs(context).edit().putInt(key, status).apply();
- }
-
- private static void clearScopedAccessPreferences(Context context, String packageName) {
- final String keySubstring = "|" + packageName + "|";
- final SharedPreferences prefs = getPrefs(context);
- Editor editor = null;
- for (final String key : prefs.getAll().keySet()) {
- if (key.contains(keySubstring)) {
- if (editor == null) {
- editor = prefs.edit();
- }
- editor.remove(key);
- }
- }
- if (editor != null) {
- editor.apply();
- }
- }
-
- private static String getScopedAccessDenialsKey(String packageName, String uuid,
- String directory) {
- final int userId = UserHandle.myUserId();
- return uuid == null
- ? userId + "|" + packageName + "||" + directory
- : userId + "|" + packageName + "|" + uuid + "|" + directory;
- }
-
public static boolean shouldBackup(String s) {
return (s != null) ? s.startsWith(ROOT_VIEW_MODE_PREFIX) : false;
}
diff --git a/src/com/android/documentsui/prefs/ScopedAccessLocalPreferences.java b/src/com/android/documentsui/prefs/ScopedAccessLocalPreferences.java
new file mode 100644
index 0000000..cd6c419
--- /dev/null
+++ b/src/com/android/documentsui/prefs/ScopedAccessLocalPreferences.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.prefs;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.UserHandle;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Methods for accessing the local preferences with regards to scoped directory access.
+ */
+//TODO(b/63720392): add unit tests
+public class ScopedAccessLocalPreferences {
+
+ private static final String TAG = "ScopedAccessLocalPreferences";
+
+ private static SharedPreferences getPrefs(Context context) {
+ return PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ public static final int PERMISSION_ASK = 0;
+ public static final int PERMISSION_ASK_AGAIN = 1;
+ public static final int PERMISSION_NEVER_ASK = -1;
+
+ @IntDef(flag = true, value = {
+ PERMISSION_ASK,
+ PERMISSION_ASK_AGAIN,
+ PERMISSION_NEVER_ASK,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionStatus {}
+
+ private static final String KEY_REGEX = "^.+\\|(.+)\\|(.*)\\|(.+)$";
+ private static final Pattern KEY_PATTERN = Pattern.compile(KEY_REGEX);
+
+ /**
+ * Methods below are used to keep track of denied user requests on scoped directory access so
+ * the dialog is not offered when user checked the 'Do not ask again' box
+ *
+ * <p>It uses a shared preferences, whose key is:
+ * <ol>
+ * <li>{@code USER_ID|PACKAGE_NAME|VOLUME_UUID|DIRECTORY} for storage volumes that have a UUID
+ * (typically physical volumes like SD cards).
+ * <li>{@code USER_ID|PACKAGE_NAME||DIRECTORY} for storage volumes that do not have a UUID
+ * (typically the emulated volume used for primary storage
+ * </ol>
+ */
+ public static @PermissionStatus int getScopedAccessPermissionStatus(Context context,
+ String packageName, @Nullable String uuid, String directory) {
+ final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
+ return getPrefs(context).getInt(key, PERMISSION_ASK);
+ }
+
+ public static void setScopedAccessPermissionStatus(Context context, String packageName,
+ @Nullable String uuid, String directory, @PermissionStatus int status) {
+ final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
+ getPrefs(context).edit().putInt(key, status).apply();
+ }
+
+ public static void clearScopedAccessPreferences(Context context, String packageName) {
+ final String keySubstring = "|" + packageName + "|";
+ final SharedPreferences prefs = getPrefs(context);
+ Editor editor = null;
+ for (final String key : prefs.getAll().keySet()) {
+ if (key.contains(keySubstring)) {
+ if (editor == null) {
+ editor = prefs.edit();
+ }
+ editor.remove(key);
+ }
+ }
+ if (editor != null) {
+ editor.apply();
+ }
+ }
+
+ private static String getScopedAccessDenialsKey(String packageName, String uuid,
+ String directory) {
+ final int userId = UserHandle.myUserId();
+ return uuid == null
+ ? userId + "|" + packageName + "||" + directory
+ : userId + "|" + packageName + "|" + uuid + "|" + directory;
+ }
+
+ /**
+ * Clears all preferences associated with a given package.
+ *
+ * <p>Typically called when a package is removed or when user asked to clear its data.
+ */
+ public static void clearPackagePreferences(Context context, String packageName) {
+ ScopedAccessLocalPreferences.clearScopedAccessPreferences(context, packageName);
+ }
+
+ /**
+ * Gets all packages that have entries in the preferences
+ */
+ public static ArraySet<String> getAllPackages(Context context) {
+ final SharedPreferences prefs = getPrefs(context);
+ final ArraySet<String> pkgs = new ArraySet<>();
+
+ for (Entry<String, ?> pref : prefs.getAll().entrySet()) {
+ final String key = pref.getKey();
+ final String pkg = getPackage(key);
+ if (pkg == null) {
+ Log.w(TAG, "getAllPackages(): error parsing pref '" + key + "'");
+ continue;
+ }
+ pkgs.add(pkg);
+ }
+ return pkgs;
+ }
+
+ /**
+ * Gets all permissions.
+ */
+ public static ArrayList<Permission> getAllPermissions(Context context) {
+ final SharedPreferences prefs = getPrefs(context);
+ final ArrayList<Permission> permissions = new ArrayList<>();
+
+ for (Entry<String, ?> pref : prefs.getAll().entrySet()) {
+ final String key = pref.getKey();
+ final Object value = pref.getValue();
+ final Integer status;
+ try {
+ status = (Integer) value;
+ } catch (Exception e) {
+ Log.w(TAG, "error gettting value for key '" + key + "': " + value);
+ continue;
+ }
+ permissions.add(getPermission(key, status));
+ }
+
+ return permissions;
+ }
+
+ public static String statusAsString(@PermissionStatus int status) {
+ switch (status) {
+ case PERMISSION_ASK:
+ return "PERMISSION_ASK";
+ case PERMISSION_ASK_AGAIN:
+ return "PERMISSION_ASK_AGAIN";
+ case PERMISSION_NEVER_ASK:
+ return "PERMISSION_NEVER_ASK";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ private static String getPackage(String key) {
+ final Matcher matcher = KEY_PATTERN.matcher(key);
+ return matcher.matches() ? matcher.group(1) : null;
+ }
+
+ private static Permission getPermission(String key, Integer status) {
+ final Matcher matcher = KEY_PATTERN.matcher(key);
+ if (!matcher.matches()) return null;
+
+ final String pkg = matcher.group(1);
+ final String uuid = matcher.group(2);
+ final String directory = matcher.group(3);
+
+ return new Permission(pkg, uuid, directory, status);
+ }
+
+ public static final class Permission {
+ public final String pkg;
+ public final String uuid;
+ public final String directory;
+ public final int status;
+
+ private Permission(String pkg, String uuid, String directory, Integer status) {
+ this.pkg = pkg;
+ this.uuid = TextUtils.isEmpty(uuid) ? null : uuid;
+ this.directory = directory;
+ this.status = status.intValue();
+ }
+
+ @Override
+ public String toString() {
+ return "Permission: [pkg=" + pkg + ", uuid=" + uuid + ", dir=" + directory + ", status="
+ + statusAsString(status) + " (" + status + ")]";
+ }
+ }
+}
diff --git a/src/com/android/documentsui/queries/SearchViewManager.java b/src/com/android/documentsui/queries/SearchViewManager.java
index 6a2790d..9e8411a 100644
--- a/src/com/android/documentsui/queries/SearchViewManager.java
+++ b/src/com/android/documentsui/queries/SearchViewManager.java
@@ -20,6 +20,8 @@
import android.annotation.Nullable;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.provider.DocumentsContract.Root;
import android.text.TextUtils;
import android.util.Log;
@@ -38,6 +40,11 @@
import com.android.documentsui.base.EventHandler;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Timer;
+import java.util.TimerTask;
/**
* Manages searching UI behavior.
@@ -48,9 +55,19 @@
private static final String TAG = "SearchManager";
+ // How long we wait after the user finishes typing before kicking off a search.
+ public static final int SEARCH_DELAY_MS = 750;
+
private final SearchManagerListener mListener;
private final EventHandler<String> mCommandProcessor;
+ private final Timer mTimer;
+ private final Handler mUiHandler;
+ private final Object mSearchLock;
+ @GuardedBy("mSearchLock")
+ private @Nullable Runnable mQueuedSearchRunnable;
+ @GuardedBy("mSearchLock")
+ private @Nullable TimerTask mQueuedSearchTask;
private @Nullable String mCurrentSearch;
private boolean mSearchExpanded;
private boolean mIgnoreNextClose;
@@ -64,12 +81,25 @@
SearchManagerListener listener,
EventHandler<String> commandProcessor,
@Nullable Bundle savedState) {
+ this(listener, commandProcessor, savedState, new Timer(),
+ new Handler(Looper.getMainLooper()));
+ }
+ @VisibleForTesting
+ protected SearchViewManager(
+ SearchManagerListener listener,
+ EventHandler<String> commandProcessor,
+ @Nullable Bundle savedState,
+ Timer timer,
+ Handler handler) {
assert (listener != null);
assert (commandProcessor != null);
+ mSearchLock = new Object();
mListener = listener;
mCommandProcessor = commandProcessor;
+ mTimer = timer;
+ mUiHandler = handler;
mCurrentSearch = savedState != null ? savedState.getString(Shared.EXTRA_QUERY) : null;
}
@@ -169,6 +199,7 @@
*/
public boolean cancelSearch() {
if (isExpanded() || isSearching()) {
+ cancelQueuedSearch();
// If the query string is not empty search view won't get iconified
mSearchView.setQuery("", false);
@@ -183,13 +214,24 @@
return false;
}
+ private void cancelQueuedSearch() {
+ synchronized (mSearchLock) {
+ if (mQueuedSearchTask != null) {
+ mQueuedSearchTask.cancel();
+ }
+ mQueuedSearchTask = null;
+ mUiHandler.removeCallbacks(mQueuedSearchRunnable);
+ mQueuedSearchRunnable = null;
+ }
+ }
+
/**
* Sets search view into the searching state. Used to restore state after device orientation
* change.
*/
private void restoreSearch() {
if (isSearching()) {
- if(mFullBar) {
+ if (mFullBar) {
mMenuItem.expandActionView();
} else {
mSearchView.setIconified(false);
@@ -202,7 +244,7 @@
private void onSearchExpanded() {
mSearchExpanded = true;
- if(mFullBar) {
+ if (mFullBar) {
mMenu.setGroupVisible(R.id.group_hide_when_searching, false);
}
@@ -228,7 +270,7 @@
mListener.onSearchChanged(mCurrentSearch);
}
- if(mFullBar) {
+ if (mFullBar) {
mMenuItem.collapseActionView();
}
mListener.onSearchFinished();
@@ -261,9 +303,13 @@
if (mCommandProcessor.accept(query)) {
mSearchView.setQuery("", false);
} else {
- mCurrentSearch = query;
+ cancelQueuedSearch();
+ // Don't kick off a search if we've already finished it.
+ if (mCurrentSearch != query) {
+ mCurrentSearch = query;
+ mListener.onSearchChanged(mCurrentSearch);
+ }
mSearchView.clearFocus();
- mListener.onSearchChanged(mCurrentSearch);
}
return true;
@@ -283,9 +329,35 @@
}
}
+ @VisibleForTesting
+ protected TimerTask createSearchTask(String newText) {
+ return new TimerTask() {
+ @Override
+ public void run() {
+ // Do the actual work on the main looper.
+ synchronized (mSearchLock) {
+ mQueuedSearchRunnable = () -> {
+ mCurrentSearch = newText;
+ if (mCurrentSearch != null && mCurrentSearch.isEmpty()) {
+ mCurrentSearch = null;
+ }
+ mListener.onSearchChanged(mCurrentSearch);
+ };
+ mUiHandler.post(mQueuedSearchRunnable);
+ }
+ }
+ };
+ }
+
@Override
public boolean onQueryTextChange(String newText) {
- return false;
+ cancelQueuedSearch();
+ synchronized (mSearchLock) {
+ mQueuedSearchTask = createSearchTask(newText);
+
+ mTimer.schedule(mQueuedSearchTask, SEARCH_DELAY_MS);
+ }
+ return true;
}
@Override
diff --git a/src/com/android/documentsui/roots/ProvidersCache.java b/src/com/android/documentsui/roots/ProvidersCache.java
index ffb01e8..e8dcbc6 100644
--- a/src/com/android/documentsui/roots/ProvidersCache.java
+++ b/src/com/android/documentsui/roots/ProvidersCache.java
@@ -396,6 +396,7 @@
}
}
+ @Override
public RootInfo getDefaultRootBlocking(State state) {
for (RootInfo root : ProvidersAccess.getMatchingRoots(getRootsBlocking(), state)) {
if (root.isDownloads()) {
diff --git a/src/com/android/documentsui/selection/BandController.java b/src/com/android/documentsui/selection/BandController.java
deleted file mode 100644
index 399bb15..0000000
--- a/src/com/android/documentsui/selection/BandController.java
+++ /dev/null
@@ -1,1160 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import static com.android.documentsui.base.Shared.DEBUG;
-import static com.android.documentsui.ui.ViewAutoScroller.NOT_SET;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.OnScrollListener;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.util.SparseIntArray;
-import android.view.View;
-
-import com.android.documentsui.DirectoryReloadLock;
-import com.android.documentsui.R;
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.dirlist.DocumentsAdapter;
-import com.android.documentsui.dirlist.FocusHandler;
-import com.android.documentsui.ui.ViewAutoScroller;
-import com.android.documentsui.ui.ViewAutoScroller.ScrollActionDelegate;
-import com.android.documentsui.ui.ViewAutoScroller.ScrollDistanceDelegate;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.IntPredicate;
-
-/**
- * Provides mouse driven band-select support when used in conjunction with {@link RecyclerView}
- * and {@link SelectionManager}. This class is responsible for rendering the band select
- * overlay and selecting overlaid items via SelectionManager.
- */
-public class BandController extends OnScrollListener {
-
- private static final String TAG = "BandController";
-
- private final Runnable mModelBuilder;
- private final SelectionEnvironment mEnvironment;
- private final DocumentsAdapter mAdapter;
- private final SelectionManager mSelectionManager;
- private final DirectoryReloadLock mLock;
- private final Runnable mViewScroller;
- private final GridModel.OnSelectionChangedListener mGridListener;
- private final List<Runnable> mStartBandSelectListeners = new ArrayList<>();
-
- @Nullable private Rect mBounds;
- @Nullable private Point mCurrentPosition;
- @Nullable private Point mOrigin;
- @Nullable private BandController.GridModel mModel;
-
- private Selection mSelection;
-
- public BandController(
- final RecyclerView view,
- DocumentsAdapter adapter,
- SelectionManager selectionManager,
- DirectoryReloadLock lock,
- IntPredicate gridItemTester) {
- this(new RuntimeSelectionEnvironment(view), adapter, selectionManager,
- lock, gridItemTester);
- }
-
- @VisibleForTesting
- BandController(
- SelectionEnvironment env,
- DocumentsAdapter adapter,
- SelectionManager selectionManager,
- DirectoryReloadLock lock,
- IntPredicate gridItemTester) {
-
- mLock = lock;
- selectionManager.bindContoller(this);
-
- mEnvironment = env;
- mAdapter = adapter;
- mSelectionManager = selectionManager;
-
- mEnvironment.addOnScrollListener(this);
- mViewScroller = new ViewAutoScroller(
- new ScrollDistanceDelegate() {
- @Override
- public Point getCurrentPosition() {
- return mCurrentPosition;
- }
-
- @Override
- public int getViewHeight() {
- return mEnvironment.getHeight();
- }
-
- @Override
- public boolean isActive() {
- return BandController.this.isActive();
- }
- },
- env);
-
- mAdapter.registerAdapterDataObserver(
- new RecyclerView.AdapterDataObserver() {
- @Override
- public void onChanged() {
- if (isActive()) {
- endBandSelect();
- }
- }
-
- @Override
- public void onItemRangeChanged(
- int startPosition, int itemCount, Object payload) {
- // No change in position. Ignoring.
- }
-
- @Override
- public void onItemRangeInserted(int startPosition, int itemCount) {
- if (isActive()) {
- endBandSelect();
- }
- }
-
- @Override
- public void onItemRangeRemoved(int startPosition, int itemCount) {
- assert(startPosition >= 0);
- assert(itemCount > 0);
-
- // TODO: Should update grid model.
- }
-
- @Override
- public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
- throw new UnsupportedOperationException();
- }
- });
-
- mGridListener = new GridModel.OnSelectionChangedListener() {
-
- @Override
- public void onSelectionChanged(Set<String> updatedSelection) {
- BandController.this.onSelectionChanged(updatedSelection);
- }
-
- @Override
- public boolean onBeforeItemStateChange(String id, boolean nextState) {
- return BandController.this.onBeforeItemStateChange(id, nextState);
- }
- };
-
- mModelBuilder = new Runnable() {
- @Override
- public void run() {
- mModel = new GridModel(mEnvironment, gridItemTester, mAdapter);
- mModel.addOnSelectionChangedListener(mGridListener);
- }
- };
- }
-
- @VisibleForTesting
- boolean isActive() {
- return mModel != null;
- }
-
- void bindSelection(Selection selection) {
- mSelection = selection;
- }
-
- public boolean onInterceptTouchEvent(InputEvent e) {
- if (shouldStart(e)) {
- if (!e.isCtrlKeyDown()) {
- mSelectionManager.clearSelection();
- }
- startBandSelect(e.getOrigin());
- } else if (shouldStop(e)) {
- endBandSelect();
- }
-
- return isActive();
- }
-
- public void addBandSelectStartedListener(Runnable listener) {
- mStartBandSelectListeners.add(listener);
- }
-
- public void removeBandSelectStartedListener(Runnable listener) {
- mStartBandSelectListeners.remove(listener);
- }
-
- /**
- * Handle a change in layout by cleaning up and getting rid of the old model and creating
- * a new model which will track the new layout.
- */
- public void handleLayoutChanged() {
- if (mModel != null) {
- mModel.removeOnSelectionChangedListener(mGridListener);
- mModel.stopListening();
-
- // build a new model, all fresh and happy.
- mModelBuilder.run();
- }
- }
-
- public boolean shouldStart(InputEvent e) {
- // Don't start, or extend bands on non-left clicks.
- if (!e.isPrimaryButtonPressed()) {
- return false;
- }
-
- if (!e.isMouseEvent() && isActive()) {
- // Weird things happen if we keep up band select
- // when touch events happen.
- endBandSelect();
- return false;
- }
-
- // b/30146357 && b/23793622. onInterceptTouchEvent does not dispatch events to onTouchEvent
- // unless the event is != ACTION_DOWN. Thus, we need to actually start band selection when
- // mouse moves, or else starting band selection on mouse down can cause problems as events
- // don't get routed correctly to onTouchEvent.
- return !isActive()
- && e.isActionMove() // the initial button move via mouse-touch (ie. down press)
- && mAdapter.hasModelIds() // we want to check against actual modelIds count to
- // avoid dummy view count from the AdapterWrapper
- && !e.isOverDragHotspot();
-
- }
-
- public boolean shouldStop(InputEvent input) {
- return isActive()
- && input.isMouseEvent()
- && (input.isActionUp() || input.isMultiPointerActionUp() || input.isActionCancel());
- }
-
- /**
- * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
- * @param input
- */
- public void onTouchEvent(InputEvent input) {
- assert(input.isMouseEvent());
-
- if (shouldStop(input)) {
- endBandSelect();
- return;
- }
-
- // We shouldn't get any events in this method when band select is not active,
- // but it turns some guests show up late to the party.
- // Probably happening when a re-layout is happening to the ReyclerView (ie. Pull-To-Refresh)
- if (!isActive()) {
- return;
- }
-
- assert(input.isActionMove());
- mCurrentPosition = input.getOrigin();
- mModel.resizeSelection(input.getOrigin());
- scrollViewIfNecessary();
- resizeBandSelectRectangle();
- }
-
- /**
- * Starts band select by adding the drawable to the RecyclerView's overlay.
- */
- private void startBandSelect(Point origin) {
- if (DEBUG) Log.d(TAG, "Starting band select @ " + origin);
-
- mLock.block();
- notifyBandSelectStartedListeners();
- mOrigin = origin;
- mModelBuilder.run(); // Creates a new selection model.
- mModel.startSelection(mOrigin);
- }
-
- private void notifyBandSelectStartedListeners() {
- for (Runnable listener : mStartBandSelectListeners) {
- listener.run();
- }
- }
-
- /**
- * Scrolls the view if necessary.
- */
- private void scrollViewIfNecessary() {
- mEnvironment.removeCallback(mViewScroller);
- mViewScroller.run();
- mEnvironment.invalidateView();
- }
-
- /**
- * Resizes the band select rectangle by using the origin and the current pointer position as
- * two opposite corners of the selection.
- */
- private void resizeBandSelectRectangle() {
- mBounds = new Rect(Math.min(mOrigin.x, mCurrentPosition.x),
- Math.min(mOrigin.y, mCurrentPosition.y),
- Math.max(mOrigin.x, mCurrentPosition.x),
- Math.max(mOrigin.y, mCurrentPosition.y));
- mEnvironment.showBand(mBounds);
- }
-
- /**
- * Ends band select by removing the overlay.
- */
- private void endBandSelect() {
- if (DEBUG) Log.d(TAG, "Ending band select.");
-
- mEnvironment.hideBand();
- mSelection.applyProvisionalSelection();
- mModel.endSelection();
- int firstSelected = mModel.getPositionNearestOrigin();
- if (firstSelected != NOT_SET) {
- if (mSelection.contains(mAdapter.getModelId(firstSelected))) {
- // TODO: firstSelected should really be lastSelected, we want to anchor the item
- // where the mouse-up occurred.
- mSelectionManager.setSelectionRangeBegin(firstSelected);
- } else {
- // TODO: Check if this is really happening.
- Log.w(TAG, "First selected by band is NOT in selection!");
- }
- }
-
- mModel = null;
- mOrigin = null;
- mLock.unblock();
- }
-
- private void onSelectionChanged(Set<String> updatedSelection) {
- Map<String, Boolean> delta = mSelection.setProvisionalSelection(updatedSelection);
- for (Map.Entry<String, Boolean> entry: delta.entrySet()) {
- mSelectionManager.notifyItemStateChanged(entry.getKey(), entry.getValue());
- }
- mSelectionManager.notifySelectionChanged();
- }
-
- private boolean onBeforeItemStateChange(String id, boolean nextState) {
- return mSelectionManager.canSetState(id, nextState);
- }
-
- @Override
- public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
- if (!isActive()) {
- return;
- }
-
- // Adjust the y-coordinate of the origin the opposite number of pixels so that the
- // origin remains in the same place relative to the view's items.
- mOrigin.y -= dy;
- resizeBandSelectRectangle();
- }
-
- /**
- * Provides a band selection item model for views within a RecyclerView. This class queries the
- * RecyclerView to determine where its items are placed; then, once band selection is underway,
- * it alerts listeners of which items are covered by the selections.
- */
- @VisibleForTesting
- static final class GridModel extends RecyclerView.OnScrollListener {
-
- public static final int NOT_SET = -1;
-
- // Enum values used to determine the corner at which the origin is located within the
- private static final int UPPER = 0x00;
- private static final int LOWER = 0x01;
- private static final int LEFT = 0x00;
- private static final int RIGHT = 0x02;
- private static final int UPPER_LEFT = UPPER | LEFT;
- private static final int UPPER_RIGHT = UPPER | RIGHT;
- private static final int LOWER_LEFT = LOWER | LEFT;
- private static final int LOWER_RIGHT = LOWER | RIGHT;
-
- private final SelectionEnvironment mHelper;
- private final IntPredicate mGridItemTester;
- private final DocumentsAdapter mAdapter;
-
- private final List<GridModel.OnSelectionChangedListener> mOnSelectionChangedListeners =
- new ArrayList<>();
-
- // Map from the x-value of the left side of a SparseBooleanArray of adapter positions, keyed
- // by their y-offset. For example, if the first column of the view starts at an x-value of 5,
- // mColumns.get(5) would return an array of positions in that column. Within that array, the
- // value for key y is the adapter position for the item whose y-offset is y.
- private final SparseArray<SparseIntArray> mColumns = new SparseArray<>();
-
- // List of limits along the x-axis (columns).
- // This list is sorted from furthest left to furthest right.
- private final List<GridModel.Limits> mColumnBounds = new ArrayList<>();
-
- // List of limits along the y-axis (rows). Note that this list only contains items which
- // have been in the viewport.
- private final List<GridModel.Limits> mRowBounds = new ArrayList<>();
-
- // The adapter positions which have been recorded so far.
- private final SparseBooleanArray mKnownPositions = new SparseBooleanArray();
-
- // Array passed to registered OnSelectionChangedListeners. One array is created and reused
- // throughout the lifetime of the object.
- private final Set<String> mSelection = new HashSet<>();
-
- // The current pointer (in absolute positioning from the top of the view).
- private Point mPointer = null;
-
- // The bounds of the band selection.
- private RelativePoint mRelativeOrigin;
- private RelativePoint mRelativePointer;
-
- private boolean mIsActive;
-
- // Tracks where the band select originated from. This is used to determine where selections
- // should expand from when Shift+click is used.
- private int mPositionNearestOrigin = NOT_SET;
-
- GridModel(SelectionEnvironment helper, IntPredicate gridItemTester, DocumentsAdapter adapter) {
- mHelper = helper;
- mAdapter = adapter;
- mGridItemTester = gridItemTester;
- mHelper.addOnScrollListener(this);
- }
-
- /**
- * Stops listening to the view's scrolls. Call this function before discarding a
- * BandSelecModel object to prevent memory leaks.
- */
- void stopListening() {
- mHelper.removeOnScrollListener(this);
- }
-
- /**
- * Start a band select operation at the given point.
- * @param relativeOrigin The origin of the band select operation, relative to the viewport.
- * For example, if the view is scrolled to the bottom, the top-left of the viewport
- * would have a relative origin of (0, 0), even though its absolute point has a higher
- * y-value.
- */
- void startSelection(Point relativeOrigin) {
- recordVisibleChildren();
- if (isEmpty()) {
- // The selection band logic works only if there is at least one visible child.
- return;
- }
-
- mIsActive = true;
- mPointer = mHelper.createAbsolutePoint(relativeOrigin);
- mRelativeOrigin = new RelativePoint(mPointer);
- mRelativePointer = new RelativePoint(mPointer);
- computeCurrentSelection();
- notifyListeners();
- }
-
- /**
- * Resizes the selection by adjusting the pointer (i.e., the corner of the selection
- * opposite the origin.
- * @param relativePointer The pointer (opposite of the origin) of the band select operation,
- * relative to the viewport. For example, if the view is scrolled to the bottom, the
- * top-left of the viewport would have a relative origin of (0, 0), even though its
- * absolute point has a higher y-value.
- */
- @VisibleForTesting
- void resizeSelection(Point relativePointer) {
- mPointer = mHelper.createAbsolutePoint(relativePointer);
- updateModel();
- }
-
- /**
- * Ends the band selection.
- */
- void endSelection() {
- mIsActive = false;
- }
-
- /**
- * @return The adapter position for the item nearest the origin corresponding to the latest
- * band select operation, or NOT_SET if the selection did not cover any items.
- */
- int getPositionNearestOrigin() {
- return mPositionNearestOrigin;
- }
-
- @Override
- public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
- if (!mIsActive) {
- return;
- }
-
- mPointer.x += dx;
- mPointer.y += dy;
- recordVisibleChildren();
- updateModel();
- }
-
- /**
- * Queries the view for all children and records their location metadata.
- */
- private void recordVisibleChildren() {
- for (int i = 0; i < mHelper.getVisibleChildCount(); i++) {
- int adapterPosition = mHelper.getAdapterPositionAt(i);
- // Sometimes the view is not attached, as we notify the multi selection manager
- // synchronously, while views are attached asynchronously. As a result items which
- // are in the adapter may not actually have a corresponding view (yet).
- if (mHelper.hasView(adapterPosition) &&
- mGridItemTester.test(adapterPosition) &&
- !mKnownPositions.get(adapterPosition)) {
- mKnownPositions.put(adapterPosition, true);
- recordItemData(mHelper.getAbsoluteRectForChildViewAt(i), adapterPosition);
- }
- }
- }
-
- /**
- * Checks if there are any recorded children.
- */
- private boolean isEmpty() {
- return mColumnBounds.size() == 0 || mRowBounds.size() == 0;
- }
-
- /**
- * Updates the limits lists and column map with the given item metadata.
- * @param absoluteChildRect The absolute rectangle for the child view being processed.
- * @param adapterPosition The position of the child view being processed.
- */
- private void recordItemData(Rect absoluteChildRect, int adapterPosition) {
- if (mColumnBounds.size() != mHelper.getColumnCount()) {
- // If not all x-limits have been recorded, record this one.
- recordLimits(
- mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right));
- }
-
- recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
-
- SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
- if (columnList == null) {
- columnList = new SparseIntArray();
- mColumns.put(absoluteChildRect.left, columnList);
- }
- columnList.put(absoluteChildRect.top, adapterPosition);
- }
-
- /**
- * Ensures limits exists within the sorted list limitsList, and adds it to the list if it
- * does not exist.
- */
- private void recordLimits(List<GridModel.Limits> limitsList, GridModel.Limits limits) {
- int index = Collections.binarySearch(limitsList, limits);
- if (index < 0) {
- limitsList.add(~index, limits);
- }
- }
-
- /**
- * Handles a moved pointer; this function determines whether the pointer movement resulted
- * in a selection change and, if it has, notifies listeners of this change.
- */
- private void updateModel() {
- RelativePoint old = mRelativePointer;
- mRelativePointer = new RelativePoint(mPointer);
- if (old != null && mRelativePointer.equals(old)) {
- return;
- }
-
- computeCurrentSelection();
- notifyListeners();
- }
-
- /**
- * Computes the currently-selected items.
- */
- private void computeCurrentSelection() {
- if (areItemsCoveredByBand(mRelativePointer, mRelativeOrigin)) {
- updateSelection(computeBounds());
- } else {
- mSelection.clear();
- mPositionNearestOrigin = NOT_SET;
- }
- }
-
- /**
- * Notifies all listeners of a selection change. Note that this function simply passes
- * mSelection, so computeCurrentSelection() should be called before this
- * function.
- */
- private void notifyListeners() {
- for (GridModel.OnSelectionChangedListener listener : mOnSelectionChangedListeners) {
- listener.onSelectionChanged(mSelection);
- }
- }
-
- /**
- * @param rect Rectangle including all covered items.
- */
- private void updateSelection(Rect rect) {
- int columnStart =
- Collections.binarySearch(mColumnBounds, new Limits(rect.left, rect.left));
- assert(columnStart >= 0);
- int columnEnd = columnStart;
-
- for (int i = columnStart; i < mColumnBounds.size()
- && mColumnBounds.get(i).lowerLimit <= rect.right; i++) {
- columnEnd = i;
- }
-
- int rowStart = Collections.binarySearch(mRowBounds, new Limits(rect.top, rect.top));
- if (rowStart < 0) {
- mPositionNearestOrigin = NOT_SET;
- return;
- }
-
- int rowEnd = rowStart;
- for (int i = rowStart; i < mRowBounds.size()
- && mRowBounds.get(i).lowerLimit <= rect.bottom; i++) {
- rowEnd = i;
- }
-
- updateSelection(columnStart, columnEnd, rowStart, rowEnd);
- }
-
- /**
- * Computes the selection given the previously-computed start- and end-indices for each
- * row and column.
- */
- private void updateSelection(
- int columnStartIndex, int columnEndIndex, int rowStartIndex, int rowEndIndex) {
- if (DEBUG) Log.d(TAG, String.format("updateSelection: %d, %d, %d, %d",
- columnStartIndex, columnEndIndex, rowStartIndex, rowEndIndex));
-
- mSelection.clear();
- for (int column = columnStartIndex; column <= columnEndIndex; column++) {
- SparseIntArray items = mColumns.get(mColumnBounds.get(column).lowerLimit);
- for (int row = rowStartIndex; row <= rowEndIndex; row++) {
- // The default return value for SparseIntArray.get is 0, which is a valid
- // position. Use a sentry value to prevent erroneously selecting item 0.
- final int rowKey = mRowBounds.get(row).lowerLimit;
- int position = items.get(rowKey, NOT_SET);
- if (position != NOT_SET) {
- String id = mAdapter.getModelId(position);
- if (id != null) {
- // The adapter inserts items for UI layout purposes that aren't associated
- // with files. Those will have a null model ID. Don't select them.
- if (canSelect(id)) {
- mSelection.add(id);
- }
- }
- if (isPossiblePositionNearestOrigin(column, columnStartIndex, columnEndIndex,
- row, rowStartIndex, rowEndIndex)) {
- // If this is the position nearest the origin, record it now so that it
- // can be returned by endSelection() later.
- mPositionNearestOrigin = position;
- }
- }
- }
- }
- }
-
- /**
- * @return True if the item is selectable.
- */
- private boolean canSelect(String id) {
- // TODO: Simplify the logic, so the check whether we can select is done in one place.
- // Consider injecting ActivityConfig, or move the checks from MultiSelectManager to
- // Selection.
- for (GridModel.OnSelectionChangedListener listener : mOnSelectionChangedListeners) {
- if (!listener.onBeforeItemStateChange(id, true)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return Returns true if the position is the nearest to the origin, or, in the case of the
- * lower-right corner, whether it is possible that the position is the nearest to the
- * origin. See comment below for reasoning for this special case.
- */
- private boolean isPossiblePositionNearestOrigin(int columnIndex, int columnStartIndex,
- int columnEndIndex, int rowIndex, int rowStartIndex, int rowEndIndex) {
- int corner = computeCornerNearestOrigin();
- switch (corner) {
- case UPPER_LEFT:
- return columnIndex == columnStartIndex && rowIndex == rowStartIndex;
- case UPPER_RIGHT:
- return columnIndex == columnEndIndex && rowIndex == rowStartIndex;
- case LOWER_LEFT:
- return columnIndex == columnStartIndex && rowIndex == rowEndIndex;
- case LOWER_RIGHT:
- // Note that in some cases, the last row will not have as many items as there
- // are columns (e.g., if there are 4 items and 3 columns, the second row will
- // only have one item in the first column). This function is invoked for each
- // position from left to right, so return true for any position in the bottom
- // row and only the right-most position in the bottom row will be recorded.
- return rowIndex == rowEndIndex;
- default:
- throw new RuntimeException("Invalid corner type.");
- }
- }
-
- /**
- * Listener for changes in which items have been band selected.
- */
- static interface OnSelectionChangedListener {
- public void onSelectionChanged(Set<String> updatedSelection);
- public boolean onBeforeItemStateChange(String id, boolean nextState);
- }
-
- void addOnSelectionChangedListener(GridModel.OnSelectionChangedListener listener) {
- mOnSelectionChangedListeners.add(listener);
- }
-
- void removeOnSelectionChangedListener(GridModel.OnSelectionChangedListener listener) {
- mOnSelectionChangedListeners.remove(listener);
- }
-
- /**
- * Limits of a view item. For example, if an item's left side is at x-value 5 and its right side
- * is at x-value 10, the limits would be from 5 to 10. Used to record the left- and right sides
- * of item columns and the top- and bottom sides of item rows so that it can be determined
- * whether the pointer is located within the bounds of an item.
- */
- private static class Limits implements Comparable<GridModel.Limits> {
- int lowerLimit;
- int upperLimit;
-
- Limits(int lowerLimit, int upperLimit) {
- this.lowerLimit = lowerLimit;
- this.upperLimit = upperLimit;
- }
-
- @Override
- public int compareTo(GridModel.Limits other) {
- return lowerLimit - other.lowerLimit;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof GridModel.Limits)) {
- return false;
- }
-
- return ((GridModel.Limits) other).lowerLimit == lowerLimit &&
- ((GridModel.Limits) other).upperLimit == upperLimit;
- }
-
- @Override
- public String toString() {
- return "(" + lowerLimit + ", " + upperLimit + ")";
- }
- }
-
- /**
- * The location of a coordinate relative to items. This class represents a general area of the
- * view as it relates to band selection rather than an explicit point. For example, two
- * different points within an item are considered to have the same "location" because band
- * selection originating within the item would select the same items no matter which point
- * was used. Same goes for points between items as well as those at the very beginning or end
- * of the view.
- *
- * Tracking a coordinate (e.g., an x-value) as a CoordinateLocation instead of as an int has the
- * advantage of tying the value to the Limits of items along that axis. This allows easy
- * selection of items within those Limits as opposed to a search through every item to see if a
- * given coordinate value falls within those Limits.
- */
- private static class RelativeCoordinate
- implements Comparable<GridModel.RelativeCoordinate> {
- /**
- * Location describing points after the last known item.
- */
- static final int AFTER_LAST_ITEM = 0;
-
- /**
- * Location describing points before the first known item.
- */
- static final int BEFORE_FIRST_ITEM = 1;
-
- /**
- * Location describing points between two items.
- */
- static final int BETWEEN_TWO_ITEMS = 2;
-
- /**
- * Location describing points within the limits of one item.
- */
- static final int WITHIN_LIMITS = 3;
-
- /**
- * The type of this coordinate, which is one of AFTER_LAST_ITEM, BEFORE_FIRST_ITEM,
- * BETWEEN_TWO_ITEMS, or WITHIN_LIMITS.
- */
- final int type;
-
- /**
- * The limits before the coordinate; only populated when type == WITHIN_LIMITS or type ==
- * BETWEEN_TWO_ITEMS.
- */
- GridModel.Limits limitsBeforeCoordinate;
-
- /**
- * The limits after the coordinate; only populated when type == BETWEEN_TWO_ITEMS.
- */
- GridModel.Limits limitsAfterCoordinate;
-
- // Limits of the first known item; only populated when type == BEFORE_FIRST_ITEM.
- GridModel.Limits mFirstKnownItem;
- // Limits of the last known item; only populated when type == AFTER_LAST_ITEM.
- GridModel.Limits mLastKnownItem;
-
- /**
- * @param limitsList The sorted limits list for the coordinate type. If this
- * CoordinateLocation is an x-value, mXLimitsList should be passed; otherwise,
- * mYLimitsList should be pased.
- * @param value The coordinate value.
- */
- RelativeCoordinate(List<GridModel.Limits> limitsList, int value) {
- int index = Collections.binarySearch(limitsList, new Limits(value, value));
-
- if (index >= 0) {
- this.type = WITHIN_LIMITS;
- this.limitsBeforeCoordinate = limitsList.get(index);
- } else if (~index == 0) {
- this.type = BEFORE_FIRST_ITEM;
- this.mFirstKnownItem = limitsList.get(0);
- } else if (~index == limitsList.size()) {
- GridModel.Limits lastLimits = limitsList.get(limitsList.size() - 1);
- if (lastLimits.lowerLimit <= value && value <= lastLimits.upperLimit) {
- this.type = WITHIN_LIMITS;
- this.limitsBeforeCoordinate = lastLimits;
- } else {
- this.type = AFTER_LAST_ITEM;
- this.mLastKnownItem = lastLimits;
- }
- } else {
- GridModel.Limits limitsBeforeIndex = limitsList.get(~index - 1);
- if (limitsBeforeIndex.lowerLimit <= value && value <= limitsBeforeIndex.upperLimit) {
- this.type = WITHIN_LIMITS;
- this.limitsBeforeCoordinate = limitsList.get(~index - 1);
- } else {
- this.type = BETWEEN_TWO_ITEMS;
- this.limitsBeforeCoordinate = limitsList.get(~index - 1);
- this.limitsAfterCoordinate = limitsList.get(~index);
- }
- }
- }
-
- int toComparisonValue() {
- if (type == BEFORE_FIRST_ITEM) {
- return mFirstKnownItem.lowerLimit - 1;
- } else if (type == AFTER_LAST_ITEM) {
- return mLastKnownItem.upperLimit + 1;
- } else if (type == BETWEEN_TWO_ITEMS) {
- return limitsBeforeCoordinate.upperLimit + 1;
- } else {
- return limitsBeforeCoordinate.lowerLimit;
- }
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof GridModel.RelativeCoordinate)) {
- return false;
- }
-
- GridModel.RelativeCoordinate otherCoordinate = (GridModel.RelativeCoordinate) other;
- return toComparisonValue() == otherCoordinate.toComparisonValue();
- }
-
- @Override
- public int compareTo(GridModel.RelativeCoordinate other) {
- return toComparisonValue() - other.toComparisonValue();
- }
- }
-
- /**
- * The location of a point relative to the Limits of nearby items; consists of both an x- and
- * y-RelativeCoordinateLocation.
- */
- private class RelativePoint {
- final GridModel.RelativeCoordinate xLocation;
- final GridModel.RelativeCoordinate yLocation;
-
- RelativePoint(Point point) {
- this.xLocation = new RelativeCoordinate(mColumnBounds, point.x);
- this.yLocation = new RelativeCoordinate(mRowBounds, point.y);
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof RelativePoint)) {
- return false;
- }
-
- RelativePoint otherPoint = (RelativePoint) other;
- return xLocation.equals(otherPoint.xLocation) && yLocation.equals(otherPoint.yLocation);
- }
- }
-
- /**
- * Generates a rectangle which contains the items selected by the pointer and origin.
- * @return The rectangle, or null if no items were selected.
- */
- private Rect computeBounds() {
- Rect rect = new Rect();
- rect.left = getCoordinateValue(
- min(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
- mColumnBounds,
- true);
- rect.right = getCoordinateValue(
- max(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
- mColumnBounds,
- false);
- rect.top = getCoordinateValue(
- min(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
- mRowBounds,
- true);
- rect.bottom = getCoordinateValue(
- max(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
- mRowBounds,
- false);
- return rect;
- }
-
- /**
- * Computes the corner of the selection nearest the origin.
- * @return
- */
- private int computeCornerNearestOrigin() {
- int cornerValue = 0;
-
- if (mRelativeOrigin.yLocation ==
- min(mRelativeOrigin.yLocation, mRelativePointer.yLocation)) {
- cornerValue |= UPPER;
- } else {
- cornerValue |= LOWER;
- }
-
- if (mRelativeOrigin.xLocation ==
- min(mRelativeOrigin.xLocation, mRelativePointer.xLocation)) {
- cornerValue |= LEFT;
- } else {
- cornerValue |= RIGHT;
- }
-
- return cornerValue;
- }
-
- private GridModel.RelativeCoordinate min(GridModel.RelativeCoordinate first, GridModel.RelativeCoordinate second) {
- return first.compareTo(second) < 0 ? first : second;
- }
-
- private GridModel.RelativeCoordinate max(GridModel.RelativeCoordinate first, GridModel.RelativeCoordinate second) {
- return first.compareTo(second) > 0 ? first : second;
- }
-
- /**
- * @return The absolute coordinate (i.e., the x- or y-value) of the given relative
- * coordinate.
- */
- private int getCoordinateValue(GridModel.RelativeCoordinate coordinate,
- List<GridModel.Limits> limitsList, boolean isStartOfRange) {
- switch (coordinate.type) {
- case RelativeCoordinate.BEFORE_FIRST_ITEM:
- return limitsList.get(0).lowerLimit;
- case RelativeCoordinate.AFTER_LAST_ITEM:
- return limitsList.get(limitsList.size() - 1).upperLimit;
- case RelativeCoordinate.BETWEEN_TWO_ITEMS:
- if (isStartOfRange) {
- return coordinate.limitsAfterCoordinate.lowerLimit;
- } else {
- return coordinate.limitsBeforeCoordinate.upperLimit;
- }
- case RelativeCoordinate.WITHIN_LIMITS:
- return coordinate.limitsBeforeCoordinate.lowerLimit;
- }
-
- throw new RuntimeException("Invalid coordinate value.");
- }
-
- private boolean areItemsCoveredByBand(
- RelativePoint first, RelativePoint second) {
- return doesCoordinateLocationCoverItems(first.xLocation, second.xLocation) &&
- doesCoordinateLocationCoverItems(first.yLocation, second.yLocation);
- }
-
- private boolean doesCoordinateLocationCoverItems(
- GridModel.RelativeCoordinate pointerCoordinate,
- GridModel.RelativeCoordinate originCoordinate) {
- if (pointerCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM &&
- originCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM) {
- return false;
- }
-
- if (pointerCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM &&
- originCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM) {
- return false;
- }
-
- if (pointerCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
- originCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
- pointerCoordinate.limitsBeforeCoordinate.equals(
- originCoordinate.limitsBeforeCoordinate) &&
- pointerCoordinate.limitsAfterCoordinate.equals(
- originCoordinate.limitsAfterCoordinate)) {
- return false;
- }
-
- return true;
- }
- }
-
- /**
- * Provides functionality for BandController. Exists primarily to tests that are
- * fully isolated from RecyclerView.
- */
- interface SelectionEnvironment extends ScrollActionDelegate {
- void showBand(Rect rect);
- void hideBand();
- void addOnScrollListener(RecyclerView.OnScrollListener listener);
- void removeOnScrollListener(RecyclerView.OnScrollListener listener);
- int getHeight();
- void invalidateView();
- Point createAbsolutePoint(Point relativePoint);
- Rect getAbsoluteRectForChildViewAt(int index);
- int getAdapterPositionAt(int index);
- int getColumnCount();
- int getChildCount();
- int getVisibleChildCount();
- /**
- * Items may be in the adapter, but without an attached view.
- */
- boolean hasView(int adapterPosition);
- }
-
- /** Recycler view facade implementation backed by good ol' RecyclerView. */
- private static final class RuntimeSelectionEnvironment implements SelectionEnvironment {
-
- private final RecyclerView mView;
- private final Drawable mBand;
-
- private boolean mIsOverlayShown = false;
-
- RuntimeSelectionEnvironment(RecyclerView view) {
- mView = view;
- mBand = mView.getContext().getTheme().getDrawable(R.drawable.band_select_overlay);
- }
-
- @Override
- public int getAdapterPositionAt(int index) {
- return mView.getChildAdapterPosition(mView.getChildAt(index));
- }
-
- @Override
- public void addOnScrollListener(RecyclerView.OnScrollListener listener) {
- mView.addOnScrollListener(listener);
- }
-
- @Override
- public void removeOnScrollListener(RecyclerView.OnScrollListener listener) {
- mView.removeOnScrollListener(listener);
- }
-
- @Override
- public Point createAbsolutePoint(Point relativePoint) {
- return new Point(relativePoint.x + mView.computeHorizontalScrollOffset(),
- relativePoint.y + mView.computeVerticalScrollOffset());
- }
-
- @Override
- public Rect getAbsoluteRectForChildViewAt(int index) {
- final View child = mView.getChildAt(index);
- final Rect childRect = new Rect();
- child.getHitRect(childRect);
- childRect.left += mView.computeHorizontalScrollOffset();
- childRect.right += mView.computeHorizontalScrollOffset();
- childRect.top += mView.computeVerticalScrollOffset();
- childRect.bottom += mView.computeVerticalScrollOffset();
- return childRect;
- }
-
- @Override
- public int getChildCount() {
- return mView.getAdapter().getItemCount();
- }
-
- @Override
- public int getVisibleChildCount() {
- return mView.getChildCount();
- }
-
- @Override
- public int getColumnCount() {
- RecyclerView.LayoutManager layoutManager = mView.getLayoutManager();
- if (layoutManager instanceof GridLayoutManager) {
- return ((GridLayoutManager) layoutManager).getSpanCount();
- }
-
- // Otherwise, it is a list with 1 column.
- return 1;
- }
-
- @Override
- public int getHeight() {
- return mView.getHeight();
- }
-
- @Override
- public void invalidateView() {
- mView.invalidate();
- }
-
- @Override
- public void runAtNextFrame(Runnable r) {
- mView.postOnAnimation(r);
- }
-
- @Override
- public void removeCallback(Runnable r) {
- mView.removeCallbacks(r);
- }
-
- @Override
- public void scrollBy(int dy) {
- mView.scrollBy(0, dy);
- }
-
- @Override
- public void showBand(Rect rect) {
- mBand.setBounds(rect);
-
- if (!mIsOverlayShown) {
- mView.getOverlay().add(mBand);
- }
- }
-
- @Override
- public void hideBand() {
- mView.getOverlay().remove(mBand);
- }
-
- @Override
- public boolean hasView(int pos) {
- return mView.findViewHolderForAdapterPosition(pos) != null;
- }
- }
-}
diff --git a/src/com/android/documentsui/selection/BandPredicate.java b/src/com/android/documentsui/selection/BandPredicate.java
new file mode 100644
index 0000000..48b154b
--- /dev/null
+++ b/src/com/android/documentsui/selection/BandPredicate.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+import android.view.View;
+
+/**
+ * Provides a means of controlling when and where band selection is initiated.
+ * This can be used to permit band initiation in non-empty areas, like in the whitespace of
+ * a bound view. This is especially useful when there is no empty space between items.
+ */
+public abstract class BandPredicate {
+
+ /** @return true if band selection can be initiated in response to the {@link MotionEvent}. */
+ public abstract boolean canInitiate(MotionEvent e);
+
+ /**
+ * A BandPredicate that allows initiation of band selection only in areas of RecyclerView
+ * that have {@link RecyclerView#NO_POSITION}. In most cases, this will be the empty areas
+ * between views.
+ */
+ public static final class NoPositionBandPredicate extends BandPredicate {
+
+ private final RecyclerView mRecView;
+
+ public NoPositionBandPredicate(RecyclerView recView) {
+ checkArgument(recView != null);
+
+ mRecView = recView;
+ }
+
+ @Override
+ public boolean canInitiate(MotionEvent e) {
+ View itemView = mRecView.findChildViewUnder(e.getX(), e.getY());
+ int position = itemView != null
+ ? mRecView.getChildAdapterPosition(itemView)
+ : RecyclerView.NO_POSITION;
+
+ return position == RecyclerView.NO_POSITION;
+ }
+ };
+}
diff --git a/src/com/android/documentsui/selection/BandSelectionHelper.java b/src/com/android/documentsui/selection/BandSelectionHelper.java
new file mode 100644
index 0000000..554dcf4
--- /dev/null
+++ b/src/com/android/documentsui/selection/BandSelectionHelper.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+import static android.support.v4.util.Preconditions.checkState;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Build;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+import com.android.documentsui.selection.SelectionHelper.StableIdProvider;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollHost;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollerCallbacks;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Provides mouse driven band-selection support when used in conjunction with a {@link RecyclerView}
+ * instance. This class is responsible for rendering a band overlay and manipulating selection
+ * status of the items it intersects with.
+ *
+ * <p> Given the recycling nature of RecyclerView items that have scrolled off-screen would not
+ * be selectable with a band that itself was partially rendered off-screen. To address this,
+ * BandSelectionController builds a model of the list/grid information presented by RecyclerView as
+ * the user interacts with items using their pointer (and the band). Selectable items that intersect
+ * with the band, both on and off screen, are selected on pointer up.
+ */
+public class BandSelectionHelper implements OnItemTouchListener {
+
+ static final boolean DEBUG = false;
+ static final String TAG = "BandController";
+
+ private final BandHost mHost;
+ private final StableIdProvider mStableIds;
+ private final RecyclerView.Adapter<?> mAdapter;
+ private final SelectionHelper mSelectionHelper;
+ private final SelectionPredicate mSelectionPredicate;
+ private final BandPredicate mBandPredicate;
+ private final ContentLock mLock;
+ private final Runnable mViewScroller;
+ private final GridModel.SelectionObserver mGridObserver;
+ private final List<Runnable> mBandStartedListeners = new ArrayList<>();
+
+ @Nullable private Rect mBounds;
+ @Nullable private Point mCurrentPosition;
+ @Nullable private Point mOrigin;
+ @Nullable private GridModel mModel;
+
+ public BandSelectionHelper(
+ BandHost host,
+ RecyclerView.Adapter<?> adapter,
+ StableIdProvider stableIds,
+ SelectionHelper selectionHelper,
+ SelectionPredicate selectionPredicate,
+ BandPredicate bandPredicate,
+ ContentLock lock) {
+
+ checkArgument(host != null);
+ checkArgument(adapter != null);
+ checkArgument(stableIds != null);
+ checkArgument(selectionHelper != null);
+ checkArgument(selectionPredicate != null);
+ checkArgument(bandPredicate != null);
+ checkArgument(lock != null);
+
+ mHost = host;
+ mStableIds = stableIds;
+ mAdapter = adapter;
+ mSelectionHelper = selectionHelper;
+ mSelectionPredicate = selectionPredicate;
+ mBandPredicate = bandPredicate;
+ mLock = lock;
+
+ mHost.addOnScrollListener(
+ new OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ BandSelectionHelper.this.onScrolled(recyclerView, dx, dy);
+ }
+ });
+
+ mViewScroller = new ViewAutoScroller(
+ new ScrollHost() {
+ @Override
+ public Point getCurrentPosition() {
+ return mCurrentPosition;
+ }
+
+ @Override
+ public int getViewHeight() {
+ return mHost.getHeight();
+ }
+
+ @Override
+ public boolean isActive() {
+ return BandSelectionHelper.this.isActive();
+ }
+ },
+ host);
+
+ mAdapter.registerAdapterDataObserver(
+ new RecyclerView.AdapterDataObserver() {
+ @Override
+ public void onChanged() {
+ if (isActive()) {
+ endBandSelect();
+ }
+ }
+
+ @Override
+ public void onItemRangeChanged(
+ int startPosition, int itemCount, Object payload) {
+ // No change in position. Ignoring.
+ }
+
+ @Override
+ public void onItemRangeInserted(int startPosition, int itemCount) {
+ if (isActive()) {
+ endBandSelect();
+ }
+ }
+
+ @Override
+ public void onItemRangeRemoved(int startPosition, int itemCount) {
+ assert(startPosition >= 0);
+ assert(itemCount > 0);
+
+ // TODO: Should update grid model.
+ }
+
+ @Override
+ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
+ throw new UnsupportedOperationException();
+ }
+ });
+
+ mGridObserver = new GridModel.SelectionObserver() {
+ @Override
+ public void onSelectionChanged(Set<String> updatedSelection) {
+ mSelectionHelper.setProvisionalSelection(updatedSelection);
+ }
+ };
+ }
+
+ @VisibleForTesting
+ boolean isActive() {
+ boolean active = mModel != null;
+ if (Build.IS_DEBUGGABLE && active) {
+ mLock.checkLocked();
+ }
+ return active;
+ }
+
+ /**
+ * Adds a new listener to be notified when band is created.
+ */
+ public void addOnBandStartedListener(Runnable listener) {
+ checkArgument(listener != null);
+
+ mBandStartedListeners.add(listener);
+ }
+
+ /**
+ * Removes listener. No-op if listener was not previously installed.
+ */
+ public void removeOnBandStartedListener(Runnable listener) {
+ mBandStartedListeners.remove(listener);
+ }
+
+ /**
+ * Clients must call reset when there are any material changes to the layout of items
+ * in RecyclerView.
+ */
+ public void reset() {
+ if (!isActive()) {
+ return;
+ }
+
+ mHost.hideBand();
+ mModel.stopCapturing();
+ mModel.onDestroy();
+ mModel = null;
+ mOrigin = null;
+ mLock.unblock();
+ }
+
+ boolean shouldStart(MotionEvent e) {
+ // Don't start, or extend bands on non-left clicks.
+ if (!MotionEvents.isPrimaryButtonPressed(e)) {
+ return false;
+ }
+
+ // TODO: Refactor to NOT have side-effects on this "should" method.
+ // Weird things happen if we keep up band select
+ // when touch events happen.
+ if (isActive() && !MotionEvents.isMouseEvent(e)) {
+ endBandSelect();
+ return false;
+ }
+
+ // b/30146357 && b/23793622. onInterceptTouchEvent does not dispatch events to onTouchEvent
+ // unless the event is != ACTION_DOWN. Thus, we need to actually start band selection when
+ // mouse moves, or else starting band selection on mouse down can cause problems as events
+ // don't get routed correctly to onTouchEvent.
+ return !isActive()
+ && MotionEvents.isActionMove(e)
+ // the initial button move via mouse-touch (ie. down press)
+ // The adapter inserts items for UI layout purposes that aren't
+ // associated with files. Checking against actual modelIds count
+ // effectively ignores those UI layout items.
+ && !mStableIds.getStableIds().isEmpty()
+ && mBandPredicate.canInitiate(e);
+ }
+
+ public boolean shouldStop(MotionEvent e) {
+ return isActive()
+ && MotionEvents.isMouseEvent(e)
+ && (MotionEvents.isActionUp(e)
+ || MotionEvents.isActionPointerUp(e)
+ || MotionEvents.isActionCancel(e));
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView unused, MotionEvent e) {
+ if (shouldStart(e)) {
+ if (!MotionEvents.isCtrlKeyPressed(e)) {
+ mSelectionHelper.clearSelection();
+ }
+
+ startBandSelect(MotionEvents.getOrigin(e));
+ return isActive();
+ }
+
+ if (shouldStop(e)) {
+ endBandSelect();
+ checkState(mModel == null);
+ // fall through to return false, because the band eeess done!
+ }
+
+ return false;
+ }
+
+ /**
+ * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
+ * @param input
+ */
+ @Override
+ public void onTouchEvent(RecyclerView unused, MotionEvent e) {
+ if (shouldStop(e)) {
+ endBandSelect();
+ return;
+ }
+
+ // We shouldn't get any events in this method when band select is not active,
+ // but it turns some guests show up late to the party.
+ // Probably happening when a re-layout is happening to the ReyclerView (ie. Pull-To-Refresh)
+ if (!isActive()) {
+ return;
+ }
+
+ assert MotionEvents.isActionMove(e);
+
+ mCurrentPosition = MotionEvents.getOrigin(e);
+ mModel.resizeSelection(mCurrentPosition);
+
+ scrollViewIfNecessary();
+ resizeBand();
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+
+ /**
+ * Starts band select by adding the drawable to the RecyclerView's overlay.
+ */
+ private void startBandSelect(Point origin) {
+ if (DEBUG) Log.d(TAG, "Starting band select @ " + origin);
+
+ reset();
+ mModel = new GridModel(mHost, mStableIds, mSelectionPredicate);
+ mModel.addOnSelectionChangedListener(mGridObserver);
+
+ mLock.block();
+ notifyBandStarted();
+ mOrigin = origin;
+ mModel.startCapturing(mOrigin);
+ }
+
+ private void notifyBandStarted() {
+ for (Runnable listener : mBandStartedListeners) {
+ listener.run();
+ }
+ }
+
+ private void scrollViewIfNecessary() {
+ mHost.removeCallback(mViewScroller);
+ mViewScroller.run();
+ mHost.invalidateView();
+ }
+
+ /**
+ * Resizes the band select rectangle by using the origin and the current pointer position as
+ * two opposite corners of the selection.
+ */
+ private void resizeBand() {
+ mBounds = new Rect(Math.min(mOrigin.x, mCurrentPosition.x),
+ Math.min(mOrigin.y, mCurrentPosition.y),
+ Math.max(mOrigin.x, mCurrentPosition.x),
+ Math.max(mOrigin.y, mCurrentPosition.y));
+
+ mHost.showBand(mBounds);
+ }
+
+ /**
+ * Ends band select by removing the overlay.
+ */
+ private void endBandSelect() {
+ if (DEBUG) Log.d(TAG, "Ending band select.");
+
+ // TODO: Currently when a band select operation ends outside
+ // of an item (e.g. in the empty area between items),
+ // getPositionNearestOrigin may return an unselected item.
+ // Since the point of this code is to establish the
+ // anchor point for subsequent range operations (SHIFT+CLICK)
+ // we really want to do a better job figuring out the last
+ // item selected (and nearest to the cursor).
+ int firstSelected = mModel.getPositionNearestOrigin();
+ if (firstSelected != GridModel.NOT_SET
+ && mSelectionHelper.isSelected(mStableIds.getStableId(firstSelected))) {
+ // Establish the band selection point as range anchor. This
+ // allows touch and keyboard based selection activities
+ // to be based on the band selection anchor point.
+ mSelectionHelper.anchorRange(firstSelected);
+ }
+
+ mSelectionHelper.mergeProvisionalSelection();
+ reset();
+ }
+
+ /**
+ * @see RecyclerView.OnScrollListener
+ */
+ private void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ if (!isActive()) {
+ return;
+ }
+
+ // Adjust the y-coordinate of the origin the opposite number of pixels so that the
+ // origin remains in the same place relative to the view's items.
+ mOrigin.y -= dy;
+ resizeBand();
+ }
+
+ /**
+ * Provides functionality for BandController. Exists primarily to tests that are
+ * fully isolated from RecyclerView.
+ */
+ public static abstract class BandHost extends ScrollerCallbacks {
+ public abstract void showBand(Rect rect);
+ public abstract void hideBand();
+ public abstract void addOnScrollListener(RecyclerView.OnScrollListener listener);
+ public abstract void removeOnScrollListener(RecyclerView.OnScrollListener listener);
+ public abstract int getHeight();
+ public abstract void invalidateView();
+ public abstract Point createAbsolutePoint(Point relativePoint);
+ public abstract Rect getAbsoluteRectForChildViewAt(int index);
+ public abstract int getAdapterPositionAt(int index);
+ public abstract int getColumnCount();
+ public abstract int getChildCount();
+ public abstract int getVisibleChildCount();
+ /**
+ * @return true if the item at adapter position is attached to a view.
+ */
+ public abstract boolean hasView(int adapterPosition);
+ }
+}
diff --git a/src/com/android/documentsui/selection/ContentLock.java b/src/com/android/documentsui/selection/ContentLock.java
new file mode 100644
index 0000000..2c87d3a
--- /dev/null
+++ b/src/com/android/documentsui/selection/ContentLock.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkState;
+import static com.android.documentsui.selection.Shared.DEBUG;
+import static com.android.documentsui.selection.Shared.TAG;
+
+import android.annotation.MainThread;
+import android.annotation.Nullable;
+import android.content.Loader;
+import android.util.Log;
+
+/**
+ * ContentLock provides a mechanism to block content from reloading while selection
+ * activities like gesture and band selection are active. Clients using live data
+ * (data loaded, for example by a {@link Loader}), should route calls to load
+ * content through this lock using {@link ContentLock#runWhenUnlocked(Runnable)}.
+ */
+public final class ContentLock {
+
+ private int mLocks = 0;
+ private @Nullable Runnable mCallback;
+
+ /**
+ * Increment the block count by 1
+ */
+ @MainThread
+ public synchronized void block() {
+ mLocks++;
+ if (DEBUG) Log.v(TAG, "Incremented content lock count to " + mLocks + ".");
+ }
+
+ /**
+ * Decrement the block count by 1; If no other object is trying to block and there exists some
+ * callback, that callback will be run
+ */
+ @MainThread
+ public synchronized void unblock() {
+ checkState(mLocks > 0);
+
+ mLocks--;
+ if (DEBUG) Log.v(TAG, "Decremented content lock count to " + mLocks + ".");
+
+ if (mLocks == 0 && mCallback != null) {
+ mCallback.run();
+ mCallback = null;
+ }
+ }
+
+ /**
+ * Attempts to run the given Runnable if not-locked, or else the Runnable is set to be ran next
+ * (replacing any previous set Runnables).
+ */
+ public synchronized void runWhenUnlocked(Runnable runnable) {
+ if (mLocks == 0) {
+ runnable.run();
+ } else {
+ mCallback = runnable;
+ }
+ }
+
+ /**
+ * Allows other selection code to perform a precondition check asserting the state is locked.
+ */
+ final void checkLocked() {
+ checkState(mLocks > 0);
+ }
+
+ /**
+ * Allows other selection code to perform a precondition check asserting the state is unlocked.
+ */
+ final void checkUnlocked() {
+ checkState(mLocks == 0);
+ }
+}
diff --git a/src/com/android/documentsui/selection/DefaultBandHost.java b/src/com/android/documentsui/selection/DefaultBandHost.java
new file mode 100644
index 0000000..6760706
--- /dev/null
+++ b/src/com/android/documentsui/selection/DefaultBandHost.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.annotation.DrawableRes;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.android.documentsui.selection.BandSelectionHelper.BandHost;
+
+/**
+ * RecyclerView backed {@link BandHost}.
+ */
+public final class DefaultBandHost extends BandHost {
+
+ private final RecyclerView mRecView;
+ private final Drawable mBand;
+
+ private boolean mIsOverlayShown;
+
+ public DefaultBandHost(RecyclerView recView, @DrawableRes int bandOverlayId) {
+
+ checkArgument(recView != null);
+
+ mRecView = recView;
+ mBand = mRecView.getContext().getTheme().getDrawable(bandOverlayId);
+
+ checkArgument(mBand != null);
+ }
+
+ @Override
+ public int getAdapterPositionAt(int index) {
+ return mRecView.getChildAdapterPosition(mRecView.getChildAt(index));
+ }
+
+ @Override
+ public void addOnScrollListener(RecyclerView.OnScrollListener listener) {
+ mRecView.addOnScrollListener(listener);
+ }
+
+ @Override
+ public void removeOnScrollListener(RecyclerView.OnScrollListener listener) {
+ mRecView.removeOnScrollListener(listener);
+ }
+
+ @Override
+ public Point createAbsolutePoint(Point relativePoint) {
+ return new Point(relativePoint.x + mRecView.computeHorizontalScrollOffset(),
+ relativePoint.y + mRecView.computeVerticalScrollOffset());
+ }
+
+ @Override
+ public Rect getAbsoluteRectForChildViewAt(int index) {
+ final View child = mRecView.getChildAt(index);
+ final Rect childRect = new Rect();
+ child.getHitRect(childRect);
+ childRect.left += mRecView.computeHorizontalScrollOffset();
+ childRect.right += mRecView.computeHorizontalScrollOffset();
+ childRect.top += mRecView.computeVerticalScrollOffset();
+ childRect.bottom += mRecView.computeVerticalScrollOffset();
+ return childRect;
+ }
+
+ @Override
+ public int getChildCount() {
+ return mRecView.getAdapter().getItemCount();
+ }
+
+ @Override
+ public int getVisibleChildCount() {
+ return mRecView.getChildCount();
+ }
+
+ @Override
+ public int getColumnCount() {
+ RecyclerView.LayoutManager layoutManager = mRecView.getLayoutManager();
+ if (layoutManager instanceof GridLayoutManager) {
+ return ((GridLayoutManager) layoutManager).getSpanCount();
+ }
+
+ // Otherwise, it is a list with 1 column.
+ return 1;
+ }
+
+ @Override
+ public int getHeight() {
+ return mRecView.getHeight();
+ }
+
+ @Override
+ public void invalidateView() {
+ mRecView.invalidate();
+ }
+
+ @Override
+ public void runAtNextFrame(Runnable r) {
+ mRecView.postOnAnimation(r);
+ }
+
+ @Override
+ public void removeCallback(Runnable r) {
+ mRecView.removeCallbacks(r);
+ }
+
+ @Override
+ public void scrollBy(int dy) {
+ mRecView.scrollBy(0, dy);
+ }
+
+ @Override
+ public void showBand(Rect rect) {
+ mBand.setBounds(rect);
+
+ if (!mIsOverlayShown) {
+ mRecView.getOverlay().add(mBand);
+ }
+ }
+
+ @Override
+ public void hideBand() {
+ mRecView.getOverlay().remove(mBand);
+ }
+
+ @Override
+ public boolean hasView(int pos) {
+ return mRecView.findViewHolderForAdapterPosition(pos) != null;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/documentsui/selection/DefaultBandPredicate.java b/src/com/android/documentsui/selection/DefaultBandPredicate.java
new file mode 100644
index 0000000..5de59d8
--- /dev/null
+++ b/src/com/android/documentsui/selection/DefaultBandPredicate.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import android.support.annotation.Nullable;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+
+/**
+ * BandPredicate that consults ItemDetails, premitting band selection to start
+ * when the event is not in the drag region of the item.
+ */
+public final class DefaultBandPredicate extends BandPredicate {
+
+ private final ItemDetailsLookup mDetailsLookup;
+
+ public DefaultBandPredicate(ItemDetailsLookup detailsLookup) {
+ checkArgument(detailsLookup != null);
+
+ mDetailsLookup = detailsLookup;
+ }
+
+ @Override
+ public boolean canInitiate(MotionEvent e) {
+ @Nullable ItemDetails details = mDetailsLookup.getItemDetails(e);
+ return (details != null)
+ ? !details.inDragRegion(e)
+ : true;
+ }
+}
diff --git a/src/com/android/documentsui/selection/DefaultSelectionHelper.java b/src/com/android/documentsui/selection/DefaultSelectionHelper.java
new file mode 100644
index 0000000..75fcacb
--- /dev/null
+++ b/src/com/android/documentsui/selection/DefaultSelectionHelper.java
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+import static android.support.v4.util.Preconditions.checkState;
+import static com.android.documentsui.selection.Shared.DEBUG;
+import static com.android.documentsui.selection.Shared.TAG;
+
+import android.support.annotation.IntDef;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Adapter;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+/**
+ * {@link SelectionHelper} providing support traditional multi-item selection on top
+ * of {@link RecyclerView}.
+ *
+ * <p>The class supports running in a single-select mode, which can be enabled
+ * by passing {@colde #MODE_SINGLE} to the constructor.
+ */
+public final class DefaultSelectionHelper extends SelectionHelper {
+
+ public static final int MODE_MULTIPLE = 0;
+ public static final int MODE_SINGLE = 1;
+
+ @IntDef(flag = true, value = {
+ MODE_MULTIPLE,
+ MODE_SINGLE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SelectionMode {}
+
+ private static final int RANGE_REGULAR = 0;
+
+ /**
+ * "Provisional" selection represents a overlay on the primary selection. A provisional
+ * selection maybe be eventually added to the primary selection, or it may be abandoned.
+ *
+ * <p>E.g. BandController creates a provisional selection while a user is actively selecting
+ * items with the band. Provisionally selected items are considered to be selected in
+ * {@link Selection#contains(String)} and related methods. A provisional may be abandoned or
+ * applied by selection components (like
+ * {@link com.android.documentsui.selection.BandSelectionHelper}).
+ *
+ * <p>A provisional selection may intersect the primary selection, however clearing the
+ * provisional selection will not affect the primary selection where the two may intersect.
+ */
+ private static final int RANGE_PROVISIONAL = 1;
+ @IntDef({
+ RANGE_REGULAR,
+ RANGE_PROVISIONAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface RangeType {}
+
+ private final Selection mSelection = new Selection();
+ private final List<SelectionObserver> mObservers = new ArrayList<>(1);
+ private final RecyclerView.Adapter<?> mAdapter;
+ private final StableIdProvider mStableIds;
+ private final SelectionPredicate mSelectionPredicate;
+ private final RecyclerView.AdapterDataObserver mAdapterObserver;
+ private final RangeCallbacks mRangeCallbacks;
+ private final boolean mSingleSelect;
+
+ private @Nullable Range mRange;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param mode single or multiple selection mode. In single selection mode
+ * users can only select a single item.
+ * @param adapter {@link Adapter} for the RecyclerView this instance is coupled with.
+ * @param stableIds client supplied class providing access to stable ids.
+ * @param selectionPredicate A predicate allowing the client to disallow selection
+ * of individual elements.
+ */
+ public DefaultSelectionHelper(
+ @SelectionMode int mode,
+ RecyclerView.Adapter<?> adapter,
+ StableIdProvider stableIds,
+ SelectionPredicate selectionPredicate) {
+
+ checkArgument(mode == MODE_SINGLE || mode == MODE_MULTIPLE);
+ checkArgument(adapter != null);
+ checkArgument(stableIds != null);
+ checkArgument(selectionPredicate != null);
+
+ mAdapter = adapter;
+ mStableIds = stableIds;
+ mSelectionPredicate = selectionPredicate;
+ mAdapterObserver = new AdapterObserver();
+ mRangeCallbacks = new RangeCallbacks();
+
+ mSingleSelect = mode == MODE_SINGLE;
+
+ mAdapter.registerAdapterDataObserver(mAdapterObserver);
+ }
+
+ @Override
+ public void addObserver(SelectionObserver callback) {
+ checkArgument(callback != null);
+ mObservers.add(callback);
+ }
+
+ @Override
+ public boolean hasSelection() {
+ return !mSelection.isEmpty();
+ }
+
+ @Override
+ public Selection getSelection() {
+ return mSelection;
+ }
+
+ @Override
+ public void copySelection(Selection dest) {
+ dest.copyFrom(mSelection);
+ }
+
+ @Override
+ public boolean isSelected(String id) {
+ return mSelection.contains(id);
+ }
+
+ @Override
+ public void restoreSelection(Selection other) {
+ setItemsSelectedQuietly(other.mSelection, true);
+ // NOTE: We intentionally don't restore provisional selection. It's provisional.
+ notifySelectionRestored();
+ }
+
+ @Override
+ public boolean setItemsSelected(Iterable<String> ids, boolean selected) {
+ boolean changed = setItemsSelectedQuietly(ids, selected);
+ notifySelectionChanged();
+ return changed;
+ }
+
+ private boolean setItemsSelectedQuietly(Iterable<String> ids, boolean selected) {
+ boolean changed = false;
+ for (String id: ids) {
+ boolean itemChanged = selected
+ ? canSetState(id, true) && mSelection.add(id)
+ : canSetState(id, false) && mSelection.remove(id);
+ if (itemChanged) {
+ notifyItemStateChanged(id, selected);
+ }
+ changed |= itemChanged;
+ }
+ return changed;
+ }
+
+ @Override
+ public void clearSelection() {
+ if (!hasSelection()) {
+ return;
+ }
+
+ Selection prev = clearSelectionQuietly();
+ notifySelectionCleared(prev);
+ notifySelectionChanged();
+ }
+
+ /**
+ * Clears the selection, without notifying selection listeners.
+ * Returns items in previous selection. Callers are responsible for notifying
+ * listeners about changes.
+ */
+ private Selection clearSelectionQuietly() {
+ mRange = null;
+
+ Selection prevSelection = new Selection();
+ if (hasSelection()) {
+ copySelection(prevSelection);
+ mSelection.clear();
+ }
+
+ return prevSelection;
+ }
+
+ @Override
+ public boolean select(String id) {
+ checkArgument(id != null);
+
+ if (!mSelection.contains(id)) {
+ if (!canSetState(id, true)) {
+ if (DEBUG) Log.d(TAG, "Select cancelled by selection predicate test.");
+ return false;
+ }
+
+ // Enforce single selection policy.
+ if (mSingleSelect && hasSelection()) {
+ Selection prev = clearSelectionQuietly();
+ notifySelectionCleared(prev);
+ }
+
+ mSelection.add(id);
+ notifyItemStateChanged(id, true);
+ notifySelectionChanged();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean deselect(String id) {
+ checkArgument(id != null);
+
+ if (mSelection.contains(id)) {
+ if (!canSetState(id, false)) {
+ if (DEBUG) Log.d(TAG, "Deselect cancelled by selection predicate test.");
+ return false;
+ }
+ mSelection.remove(id);
+ notifyItemStateChanged(id, false);
+ notifySelectionChanged();
+ if (mSelection.isEmpty() && isRangeActive()) {
+ // if there's nothing in the selection and there is an active ranger it results
+ // in unexpected behavior when the user tries to start range selection: the item
+ // which the ranger 'thinks' is the already selected anchor becomes unselectable
+ endRange();
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void startRange(int pos) {
+ select(mStableIds.getStableId(pos));
+ anchorRange(pos);
+ }
+
+ @Override
+ public void extendRange(int pos) {
+ extendRange(pos, RANGE_REGULAR);
+ }
+
+ @Override
+ public void endRange() {
+ mRange = null;
+ // Clean up in case there was any leftover provisional selection
+ clearProvisionalSelection();
+ }
+
+ @Override
+ public void anchorRange(int position) {
+ checkArgument(position != RecyclerView.NO_POSITION);
+
+ // TODO: I'm not a fan of silently ignoring calls.
+ // Determine if there are any cases where method can be called
+ // w/o item already being selected. Else, tighten up the ship
+ // and make this conditional guard into a proper precondition check.
+ if (mSelection.contains(mStableIds.getStableId(position))) {
+ mRange = new Range(mRangeCallbacks, position);
+ }
+ }
+
+ @Override
+ public void extendProvisionalRange(int pos) {
+ extendRange(pos, RANGE_PROVISIONAL);
+ }
+
+ /**
+ * Sets the end point for the current range selection, started by a call to
+ * {@link #startRange(int)}. This function should only be called when a range selection
+ * is active (see {@link #isRangeActive()}. Items in the range [anchor, end] will be
+ * selected or in provisional select, depending on the type supplied. Note that if the type is
+ * provisional selection, one should do {@link #mergeProvisionalSelection()} at some
+ * point before calling on {@link #endRange()}.
+ *
+ * @param pos The new end position for the selection range.
+ * @param type The type of selection the range should utilize.
+ */
+ private void extendRange(int pos, @RangeType int type) {
+ checkState(isRangeActive(), "Range start point not set.");
+
+ mRange.extendSelection(pos, type);
+
+ // We're being lazy here notifying even when something might not have changed.
+ // To make this more correct, we'd need to update the Ranger class to return
+ // information about what has changed.
+ notifySelectionChanged();
+ }
+
+ @Override
+ public void setProvisionalSelection(Set<String> newSelection) {
+ Map<String, Boolean> delta = mSelection.setProvisionalSelection(newSelection);
+ for (Map.Entry<String, Boolean> entry: delta.entrySet()) {
+ notifyItemStateChanged(entry.getKey(), entry.getValue());
+ }
+
+ notifySelectionChanged();
+ }
+
+ @Override
+ public void mergeProvisionalSelection() {
+ mSelection.mergeProvisionalSelection();
+ }
+
+ @Override
+ public void clearProvisionalSelection() {
+ for (String id : mSelection.mProvisionalSelection) {
+ notifyItemStateChanged(id, false);
+ }
+ mSelection.clearProvisionalSelection();
+ }
+
+ @Override
+ public boolean isRangeActive() {
+ return mRange != null;
+ }
+
+ private boolean canSetState(String id, boolean nextState) {
+ return mSelectionPredicate.canSetStateForId(id, nextState);
+ }
+
+ private void onDataSetChanged() {
+ // Update the selection to remove any disappeared IDs.
+ mSelection.clearProvisionalSelection();
+ mSelection.intersect(mStableIds.getStableIds());
+ notifySelectionReset();
+
+ for (String id : mSelection) {
+ // If the underlying data set has changed, before restoring
+ // selection we must re-verify that it can be selected.
+ // Why? Because if the dataset has changed, then maybe the
+ // selectability of an item has changed.
+ if (!canSetState(id, true)) {
+ deselect(id);
+ } else {
+ int lastListener = mObservers.size() - 1;
+ for (int i = lastListener; i >= 0; i--) {
+ mObservers.get(i).onItemStateChanged(id, true);
+ }
+ }
+ }
+ notifySelectionChanged();
+ }
+
+ private void onDataSetItemRangeInserted(int startPosition, int itemCount) {
+ mSelection.clearProvisionalSelection();
+ }
+
+ private void onDataSetItemRangeRemoved(int startPosition, int itemCount) {
+ checkArgument(startPosition >= 0);
+ checkArgument(itemCount > 0);
+
+ mSelection.clearProvisionalSelection();
+
+ // Remove any disappeared IDs from the selection.
+ //
+ // Ideally there could be a cheaper approach, checking
+ // each position individually, but since the source of
+ // truth for stable ids (StableIdProvider) probably
+ // it-self no-longer knows about the positions in question
+ // we fall back to the sledge hammer approach.
+ mSelection.intersect(mStableIds.getStableIds());
+ }
+
+ /**
+ * Notifies registered listeners when the selection status of a single item
+ * (identified by {@code position}) changes.
+ */
+ private void notifyItemStateChanged(String id, boolean selected) {
+ checkArgument(id != null);
+
+ int lastListenerIndex = mObservers.size() - 1;
+ for (int i = lastListenerIndex; i >= 0; i--) {
+ mObservers.get(i).onItemStateChanged(id, selected);
+ }
+
+ int position = mStableIds.getPosition(id);
+ if (DEBUG) Log.d(TAG, "ITEM " + id + " CHANGED at pos: " + position);
+
+ if (position >= 0) {
+ mAdapter.notifyItemChanged(position, SelectionHelper.SELECTION_CHANGED_MARKER);
+ } else {
+ Log.w(TAG, "Item change notification received for unknown item: " + id);
+ }
+ }
+
+ private void notifySelectionCleared(Selection selection) {
+ for (String id: selection.mSelection) {
+ notifyItemStateChanged(id, false);
+ }
+ for (String id: selection.mProvisionalSelection) {
+ notifyItemStateChanged(id, false);
+ }
+ }
+
+ /**
+ * Notifies registered listeners when the selection has changed. This
+ * notification should be sent only once a full series of changes
+ * is complete, e.g. clearingSelection, or updating the single
+ * selection from one item to another.
+ */
+ private void notifySelectionChanged() {
+ int lastListenerIndex = mObservers.size() - 1;
+ for (int i = lastListenerIndex; i >= 0; i--) {
+ mObservers.get(i).onSelectionChanged();
+ }
+ }
+
+ private void notifySelectionRestored() {
+ int lastListenerIndex = mObservers.size() - 1;
+ for (int i = lastListenerIndex; i >= 0; i--) {
+ mObservers.get(i).onSelectionRestored();
+ }
+ }
+
+ private void notifySelectionReset() {
+ int lastListenerIndex = mObservers.size() - 1;
+ for (int i = lastListenerIndex; i >= 0; i--) {
+ mObservers.get(i).onSelectionReset();
+ }
+ }
+
+ private void updateForRange(int begin, int end, boolean selected, @RangeType int type) {
+ switch (type) {
+ case RANGE_REGULAR:
+ updateForRegularRange(begin, end, selected);
+ break;
+ case RANGE_PROVISIONAL:
+ updateForProvisionalRange(begin, end, selected);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid range type: " + type);
+ }
+ }
+
+ private void updateForRegularRange(int begin, int end, boolean selected) {
+ checkArgument(end >= begin);
+
+ for (int i = begin; i <= end; i++) {
+ String id = mStableIds.getStableId(i);
+ if (id == null) {
+ continue;
+ }
+
+ if (selected) {
+ select(id);
+ } else {
+ deselect(id);
+ }
+ }
+ }
+
+ private void updateForProvisionalRange(int begin, int end, boolean selected) {
+ checkArgument(end >= begin);
+
+ for (int i = begin; i <= end; i++) {
+ String id = mStableIds.getStableId(i);
+ if (id == null) {
+ continue;
+ }
+
+ boolean changedState = false;
+ if (selected) {
+ boolean canSelect = canSetState(id, true);
+ if (canSelect && !mSelection.mSelection.contains(id)) {
+ mSelection.mProvisionalSelection.add(id);
+ changedState = true;
+ }
+ } else {
+ mSelection.mProvisionalSelection.remove(id);
+ changedState = true;
+ }
+
+ // Only notify item callbacks when something's state is actually changed in provisional
+ // selection.
+ if (changedState) {
+ notifyItemStateChanged(id, selected);
+ }
+ }
+
+ notifySelectionChanged();
+ }
+
+ private final class AdapterObserver extends RecyclerView.AdapterDataObserver {
+ @Override
+ public void onChanged() {
+ onDataSetChanged();
+ }
+
+ @Override
+ public void onItemRangeChanged(
+ int startPosition, int itemCount, Object payload) {
+ // No change in position. Ignore, since we assume
+ // selection is a user driven activity. So changes
+ // in properties of items shouldn't result in a
+ // change of selection.
+ }
+
+ @Override
+ public void onItemRangeInserted(int startPosition, int itemCount) {
+ onDataSetItemRangeInserted(startPosition, itemCount);
+ }
+
+ @Override
+ public void onItemRangeRemoved(int startPosition, int itemCount) {
+ onDataSetItemRangeRemoved(startPosition, itemCount);
+ }
+
+ @Override
+ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private final class RangeCallbacks extends Range.Callbacks {
+ @Override
+ void updateForRange(int begin, int end, boolean selected, int type) {
+ switch (type) {
+ case RANGE_REGULAR:
+ updateForRegularRange(begin, end, selected);
+ break;
+ case RANGE_PROVISIONAL:
+ updateForProvisionalRange(begin, end, selected);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid range type: " + type);
+ }
+ }
+ }
+}
diff --git a/src/com/android/documentsui/selection/GestureRouter.java b/src/com/android/documentsui/selection/GestureRouter.java
new file mode 100644
index 0000000..b336450
--- /dev/null
+++ b/src/com/android/documentsui/selection/GestureRouter.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkNotNull;
+
+import android.support.annotation.Nullable;
+import android.view.GestureDetector.OnDoubleTapListener;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+
+/**
+ * GestureRouter is responsible for routing gestures detected by a GestureDetector
+ * to registered handlers. The primary function is to divide events by tool-type
+ * allowing handlers to cleanly implement tool-type specific policies.
+ */
+public final class GestureRouter<T extends OnGestureListener & OnDoubleTapListener>
+ implements OnGestureListener, OnDoubleTapListener {
+
+ private final ToolHandlerRegistry<T> mDelegates;
+
+ public GestureRouter(T defaultDelegate) {
+ checkNotNull(defaultDelegate);
+ mDelegates = new ToolHandlerRegistry<>(defaultDelegate);
+ }
+
+ public GestureRouter() {
+ this((T) new SimpleOnGestureListener());
+ }
+
+ /**
+ * @param toolType
+ * @param delegate the delegate, or null to unregister.
+ */
+ public void register(int toolType, @Nullable T delegate) {
+ mDelegates.set(toolType, delegate);
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ return mDelegates.get(e).onSingleTapConfirmed(e);
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ return mDelegates.get(e).onDoubleTap(e);
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent e) {
+ return mDelegates.get(e).onDoubleTapEvent(e);
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return mDelegates.get(e).onDown(e);
+ }
+
+ @Override
+ public void onShowPress(MotionEvent e) {
+ mDelegates.get(e).onShowPress(e);
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ return mDelegates.get(e).onSingleTapUp(e);
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ return mDelegates.get(e2).onScroll(e1, e2, distanceX, distanceY);
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+ mDelegates.get(e).onLongPress(e);
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ return mDelegates.get(e2).onFling(e1, e2, velocityX, velocityY);
+ }
+}
diff --git a/src/com/android/documentsui/selection/GestureSelectionHelper.java b/src/com/android/documentsui/selection/GestureSelectionHelper.java
new file mode 100644
index 0000000..f3456fd
--- /dev/null
+++ b/src/com/android/documentsui/selection/GestureSelectionHelper.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+import static android.support.v4.util.Preconditions.checkState;
+
+import android.graphics.Point;
+import android.os.Build;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.documentsui.selection.ViewAutoScroller.ScrollHost;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollerCallbacks;
+
+/**
+ * GestureSelectionHelper provides logic that interprets a combination
+ * of motions and gestures in order to provide gesture driven selection support
+ * when used in conjunction with RecyclerView and other classes in the ReyclerView
+ * selection support package.
+ */
+public final class GestureSelectionHelper extends ScrollHost implements OnItemTouchListener {
+
+ private static final String TAG = "GestureSelectionHelper";
+
+ private final SelectionHelper mSelectionMgr;
+ private final Runnable mScroller;
+ private final ViewDelegate mView;
+ private final ContentLock mLock;
+
+ private int mLastStartedItemPos = -1;
+ private boolean mStarted = false;
+ private Point mLastInterceptedPoint;
+
+ /**
+ * See {@link #create(SelectionHelper, RecyclerView, ContentLock)} for convenience
+ * method.
+ */
+ @VisibleForTesting
+ GestureSelectionHelper(
+ SelectionHelper selectionHelper,
+ ViewDelegate view,
+ ContentLock lock) {
+
+ checkArgument(selectionHelper != null);
+ checkArgument(view != null);
+ checkArgument(lock != null);
+
+ mSelectionMgr = selectionHelper;
+ mView = view;
+ mLock = lock;
+
+ mScroller = new ViewAutoScroller(this, mView);
+ }
+
+ /**
+ * Explicitly kicks off a gesture multi-select.
+ *
+ * @return true if started.
+ */
+ public void start() {
+ checkState(!mStarted);
+ checkState(mLastStartedItemPos > -1);
+
+ // Partner code in MotionInputHandler ensures items
+ // are selected and range established prior to
+ // start being called.
+ // Verify the truth of that statement here
+ // to make the implicit coupling less of a time bomb.
+ checkState(mSelectionMgr.isRangeActive());
+
+ mLock.checkUnlocked();
+
+ mStarted = true;
+ mLock.block();
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView unused, MotionEvent e) {
+ if (MotionEvents.isMouseEvent(e)) {
+ if (Shared.DEBUG) Log.w(TAG, "Unexpected Mouse event. Check configuration.");
+ }
+
+ switch (e.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ // NOTE: Unlike events with other actions, RecyclerView eats
+ // "DOWN" events. So even if we return true here we'll
+ // never see an event w/ ACTION_DOWN passed to onTouchEvent.
+ return handleInterceptedDownEvent(e);
+ case MotionEvent.ACTION_MOVE:
+ return mStarted;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView unused, MotionEvent e) {
+ // Note: There were a couple times I as this check firing
+ // after combinations of mouse + touch + rotation.
+ // But after further investigation I couldn't repro.
+ // For that reason we guard this check (for now) w/ IS_DEBUGGABLE.
+ if (Build.IS_DEBUGGABLE) checkState(mStarted);
+
+ switch (e.getActionMasked()) {
+ case MotionEvent.ACTION_MOVE:
+ handleMoveEvent(e);
+ break;
+ case MotionEvent.ACTION_UP:
+ handleUpEvent(e);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ handleCancelEvent(e);
+ break;
+ }
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+
+ // Called when an ACTION_DOWN event is intercepted.
+ // If down event happens on an item, we mark that item's position as last started.
+ private boolean handleInterceptedDownEvent(MotionEvent e) {
+ mLastStartedItemPos = mView.getItemUnder(e);
+ return mLastStartedItemPos != RecyclerView.NO_POSITION;
+ }
+
+ // Called when ACTION_UP event is to be handled.
+ // Essentially, since this means all gesture movement is over, reset everything and apply
+ // provisional selection.
+ private void handleUpEvent(MotionEvent e) {
+ mSelectionMgr.mergeProvisionalSelection();
+ endSelection();
+ if (mLastStartedItemPos > -1) {
+ mSelectionMgr.startRange(mLastStartedItemPos);
+ }
+ }
+
+ // Called when ACTION_CANCEL event is to be handled.
+ // This means this gesture selection is aborted, so reset everything and abandon provisional
+ // selection.
+ private void handleCancelEvent(MotionEvent unused) {
+ mSelectionMgr.clearProvisionalSelection();
+ endSelection();
+ }
+
+ private void endSelection() {
+ checkState(mStarted);
+
+ mLastStartedItemPos = -1;
+ mStarted = false;
+ mLock.unblock();
+ }
+
+ // Call when an intercepted ACTION_MOVE event is passed down.
+ // At this point, we are sure user wants to gesture multi-select.
+ private void handleMoveEvent(MotionEvent e) {
+ mLastInterceptedPoint = MotionEvents.getOrigin(e);
+
+ int lastGlidedItemPos = mView.getLastGlidedItemPosition(e);
+ if (lastGlidedItemPos != RecyclerView.NO_POSITION) {
+ doGestureMultiSelect(lastGlidedItemPos);
+ }
+ scrollIfNecessary();
+ }
+
+ // It's possible for events to go over the top/bottom of the RecyclerView.
+ // We want to get a Y-coordinate within the RecyclerView so we can find the childView underneath
+ // correctly.
+ private static float getInboundY(float max, float y) {
+ if (y < 0f) {
+ return 0f;
+ } else if (y > max) {
+ return max;
+ }
+ return y;
+ }
+
+ /* Given the end position, select everything in-between.
+ * @param endPos The adapter position of the end item.
+ */
+ private void doGestureMultiSelect(int endPos) {
+ mSelectionMgr.extendProvisionalRange(endPos);
+ }
+
+ private void scrollIfNecessary() {
+ mScroller.run();
+ }
+
+ @Override
+ public Point getCurrentPosition() {
+ return mLastInterceptedPoint;
+ }
+
+ @Override
+ public int getViewHeight() {
+ return mView.getHeight();
+ }
+
+ @Override
+ public boolean isActive() {
+ return mStarted && mSelectionMgr.hasSelection();
+ }
+
+ /**
+ * Returns a new instance of GestureSelectionHelper.
+ */
+ public static GestureSelectionHelper create(
+ SelectionHelper selectionMgr, RecyclerView recycler, ContentLock lock) {
+
+ return new GestureSelectionHelper(
+ selectionMgr, new RecyclerViewDelegate(recycler), lock);
+ }
+
+ @VisibleForTesting
+ static abstract class ViewDelegate extends ScrollerCallbacks {
+ abstract int getHeight();
+ abstract int getItemUnder(MotionEvent e);
+ abstract int getLastGlidedItemPosition(MotionEvent e);
+ }
+
+ @VisibleForTesting
+ static final class RecyclerViewDelegate extends ViewDelegate {
+
+ private final RecyclerView mView;
+
+ RecyclerViewDelegate(RecyclerView view) {
+ checkArgument(view != null);
+ mView = view;
+ }
+
+ @Override
+ int getHeight() {
+ return mView.getHeight();
+ }
+
+ @Override
+ int getItemUnder(MotionEvent e) {
+ View child = mView.findChildViewUnder(e.getX(), e.getY());
+ return child != null
+ ? mView.getChildAdapterPosition(child)
+ : RecyclerView.NO_POSITION;
+ }
+
+ @Override
+ int getLastGlidedItemPosition(MotionEvent e) {
+ // If user has moved his pointer to the bottom-right empty pane (ie. to the right of the
+ // last item of the recycler view), we would want to set that as the currentItemPos
+ View lastItem = mView.getLayoutManager()
+ .getChildAt(mView.getLayoutManager().getChildCount() - 1);
+ int direction =
+ mView.getContext().getResources().getConfiguration().getLayoutDirection();
+ final boolean pastLastItem = isPastLastItem(lastItem.getTop(),
+ lastItem.getLeft(),
+ lastItem.getRight(),
+ e,
+ direction);
+
+ // Since views get attached & detached from RecyclerView,
+ // {@link LayoutManager#getChildCount} can return a different number from the actual
+ // number
+ // of items in the adapter. Using the adapter is the for sure way to get the actual last
+ // item position.
+ final float inboundY = getInboundY(mView.getHeight(), e.getY());
+ return (pastLastItem) ? mView.getAdapter().getItemCount() - 1
+ : mView.getChildAdapterPosition(mView.findChildViewUnder(e.getX(), inboundY));
+ }
+
+ /*
+ * Check to see if MotionEvent if past a particular item, i.e. to the right or to the bottom
+ * of the item.
+ * For RTL, it would to be to the left or to the bottom of the item.
+ */
+ @VisibleForTesting
+ static boolean isPastLastItem(int top, int left, int right, MotionEvent e, int direction) {
+ if (direction == View.LAYOUT_DIRECTION_LTR) {
+ return e.getX() > right && e.getY() > top;
+ } else {
+ return e.getX() < left && e.getY() > top;
+ }
+ }
+
+ @Override
+ public void scrollBy(int dy) {
+ mView.scrollBy(0, dy);
+ }
+
+ @Override
+ public void runAtNextFrame(Runnable r) {
+ mView.postOnAnimation(r);
+ }
+
+ @Override
+ public void removeCallback(Runnable r) {
+ mView.removeCallbacks(r);
+ }
+ }
+}
diff --git a/src/com/android/documentsui/selection/GestureSelector.java b/src/com/android/documentsui/selection/GestureSelector.java
deleted file mode 100644
index 7c5f217..0000000
--- a/src/com/android/documentsui/selection/GestureSelector.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import static com.android.documentsui.base.Shared.DEBUG;
-
-import android.graphics.Point;
-import android.support.annotation.VisibleForTesting;
-import android.support.v7.widget.RecyclerView;
-import android.util.Log;
-import android.view.View;
-
-import com.android.documentsui.DirectoryReloadLock;
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.ui.ViewAutoScroller;
-import com.android.documentsui.ui.ViewAutoScroller.ScrollActionDelegate;
-import com.android.documentsui.ui.ViewAutoScroller.ScrollDistanceDelegate;
-
-import java.util.function.IntSupplier;
-
-import javax.annotation.Nullable;
-
-/*
- * Helper class used to intercept events that could cause a gesture multi-select, and keeps
- * the interception going if necessary.
- */
-public final class GestureSelector {
- private final String TAG = "GestureSelector";
-
- private final SelectionManager mSelectionMgr;
- private final Runnable mDragScroller;
- private final IntSupplier mHeight;
- private final ViewFinder mViewFinder;
- private final DirectoryReloadLock mLock;
- private int mLastStartedItemPos = -1;
- private boolean mStarted = false;
- private Point mLastInterceptedPoint;
-
- GestureSelector(
- SelectionManager selectionMgr,
- IntSupplier heightSupplier,
- ViewFinder viewFinder,
- ScrollActionDelegate actionDelegate,
- DirectoryReloadLock lock) {
- mSelectionMgr = selectionMgr;
- mHeight = heightSupplier;
- mViewFinder = viewFinder;
- mLock = lock;
-
- ScrollDistanceDelegate distanceDelegate = new ScrollDistanceDelegate() {
- @Override
- public Point getCurrentPosition() {
- return mLastInterceptedPoint;
- }
-
- @Override
- public int getViewHeight() {
- return mHeight.getAsInt();
- }
-
- @Override
- public boolean isActive() {
- return mStarted && mSelectionMgr.hasSelection();
- }
- };
-
- mDragScroller = new ViewAutoScroller(distanceDelegate, actionDelegate);
- }
-
- public static GestureSelector create(
- SelectionManager selectionMgr,
- RecyclerView scrollView,
- DirectoryReloadLock lock) {
- ScrollActionDelegate actionDelegate = new ScrollActionDelegate() {
- @Override
- public void scrollBy(int dy) {
- scrollView.scrollBy(0, dy);
- }
-
- @Override
- public void runAtNextFrame(Runnable r) {
- scrollView.postOnAnimation(r);
- }
-
- @Override
- public void removeCallback(Runnable r) {
- scrollView.removeCallbacks(r);
- }
- };
- GestureSelector helper =
- new GestureSelector(
- selectionMgr,
- scrollView::getHeight,
- scrollView::findChildViewUnder,
- actionDelegate,
- lock);
-
- return helper;
- }
-
- // Explicitly kick off a gesture multi-select.
- public boolean start(InputEvent event) {
- //the anchor must already be set before a multi-select event can be started
- if (mLastStartedItemPos < 0) {
- if (DEBUG) Log.d(TAG, "Tried to start multi-select without setting an anchor.");
- return false;
- }
- if (mStarted) {
- return false;
- }
- mStarted = true;
- return true;
- }
-
- public boolean onInterceptTouchEvent(InputEvent e) {
- if (e.isMouseEvent()) {
- return false;
- }
-
- boolean handled = false;
-
- if (e.isActionDown()) {
- handled = handleInterceptedDownEvent(e);
- }
-
- if (e.isActionMove()) {
- handled = handleInterceptedMoveEvent(e);
- }
-
- return handled;
- }
-
- public void onTouchEvent(RecyclerView rv, InputEvent e) {
- if (!mStarted) {
- return;
- }
-
- if (e.isActionUp()) {
- handleUpEvent(e);
- }
-
- if (e.isActionCancel()) {
- handleCancelEvent(e);
- }
-
- if (e.isActionMove()) {
- handleOnTouchMoveEvent(rv, e);
- }
- }
-
- // Called when an ACTION_DOWN event is intercepted.
- // If down event happens on a file/doc, we mark that item's position as last started.
- private boolean handleInterceptedDownEvent(InputEvent e) {
- View itemView = mViewFinder.findView(e.getX(), e.getY());
- if (itemView != null) {
- mLastStartedItemPos = e.getItemPosition();
- }
- return false;
- }
-
- // Called when an ACTION_MOVE event is intercepted.
- private boolean handleInterceptedMoveEvent(InputEvent e) {
- mLastInterceptedPoint = e.getOrigin();
- if (mStarted) {
- mSelectionMgr.startRangeSelection(mLastStartedItemPos);
- // Gesture Selection about to start
- mLock.block();
- return true;
- }
- return false;
- }
-
- // Called when ACTION_UP event is to be handled.
- // Essentially, since this means all gesture movement is over, reset everything and apply
- // provisional selection.
- private void handleUpEvent(InputEvent e) {
- mSelectionMgr.getSelection().applyProvisionalSelection();
- endSelection();
- }
-
- // Called when ACTION_CANCEL event is to be handled.
- // This means this gesture selection is aborted, so reset everything and abandon provisional
- // selection.
- private void handleCancelEvent(InputEvent e) {
- mSelectionMgr.cancelProvisionalSelection();
- endSelection();
- }
-
- private void endSelection() {
- assert(mStarted);
- mLastStartedItemPos = -1;
- mStarted = false;
- mLock.unblock();
- }
-
- // Call when an intercepted ACTION_MOVE event is passed down.
- // At this point, we are sure user wants to gesture multi-select.
- private void handleOnTouchMoveEvent(RecyclerView rv, InputEvent e) {
- mLastInterceptedPoint = e.getOrigin();
-
- // If user has moved his pointer to the bottom-right empty pane (ie. to the right of the
- // last item of the recycler view), we would want to set that as the currentItemPos
- View lastItem = rv.getLayoutManager()
- .getChildAt(rv.getLayoutManager().getChildCount() - 1);
- int direction = rv.getContext().getResources().getConfiguration().getLayoutDirection();
- final boolean pastLastItem = isPastLastItem(lastItem.getTop(),
- lastItem.getLeft(),
- lastItem.getRight(),
- e,
- direction);
-
- // Since views get attached & detached from RecyclerView,
- // {@link LayoutManager#getChildCount} can return a different number from the actual
- // number
- // of items in the adapter. Using the adapter is the for sure way to get the actual last
- // item position.
- final float inboundY = getInboundY(rv.getHeight(), e.getY());
- final int lastGlidedItemPos = (pastLastItem) ? rv.getAdapter().getItemCount() - 1
- : rv.getChildAdapterPosition(rv.findChildViewUnder(e.getX(), inboundY));
- if (lastGlidedItemPos != RecyclerView.NO_POSITION) {
- doGestureMultiSelect(lastGlidedItemPos);
- }
- scrollIfNecessary();
- }
-
- // It's possible for events to go over the top/bottom of the RecyclerView.
- // We want to get a Y-coordinate within the RecyclerView so we can find the childView underneath
- // correctly.
- private static float getInboundY(float max, float y) {
- if (y < 0f) {
- return 0f;
- } else if (y > max) {
- return max;
- }
- return y;
- }
-
- /*
- * Check to see an InputEvent if past a particular item, i.e. to the right or to the bottom
- * of the item.
- * For RTL, it would to be to the left or to the bottom of the item.
- */
- @VisibleForTesting
- static boolean isPastLastItem(int top, int left, int right, InputEvent e, int direction) {
- if (direction == View.LAYOUT_DIRECTION_LTR) {
- return e.getX() > right && e.getY() > top;
- } else {
- return e.getX() < left && e.getY() > top;
- }
- }
-
- /* Given the end position, select everything in-between.
- * @param endPos The adapter position of the end item.
- */
- private void doGestureMultiSelect(int endPos) {
- mSelectionMgr.snapProvisionalRangeSelection(endPos);
- }
-
- private void scrollIfNecessary() {
- mDragScroller.run();
- }
-
- @FunctionalInterface
- interface ViewFinder {
- @Nullable View findView(float x, float y);
- }
-}
\ No newline at end of file
diff --git a/src/com/android/documentsui/selection/GridModel.java b/src/com/android/documentsui/selection/GridModel.java
new file mode 100644
index 0000000..dae445d
--- /dev/null
+++ b/src/com/android/documentsui/selection/GridModel.java
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+
+import com.android.documentsui.selection.BandSelectionHelper.BandHost;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+import com.android.documentsui.selection.SelectionHelper.StableIdProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Provides a band selection item model for views within a RecyclerView. This class queries the
+ * RecyclerView to determine where its items are placed; then, once band selection is underway,
+ * it alerts listeners of which items are covered by the selections.
+ */
+final class GridModel {
+
+ // Magical value indicating that a value has not been previously set. primitive null :)
+ static final int NOT_SET = -1;
+
+ // Enum values used to determine the corner at which the origin is located within the
+ private static final int UPPER = 0x00;
+ private static final int LOWER = 0x01;
+ private static final int LEFT = 0x00;
+ private static final int RIGHT = 0x02;
+ private static final int UPPER_LEFT = UPPER | LEFT;
+ private static final int UPPER_RIGHT = UPPER | RIGHT;
+ private static final int LOWER_LEFT = LOWER | LEFT;
+ private static final int LOWER_RIGHT = LOWER | RIGHT;
+
+ private final BandHost mHost;
+ private final StableIdProvider mStableIds;
+ private final SelectionPredicate mSelectionPredicate;
+
+ private final List<SelectionObserver> mOnSelectionChangedListeners =
+ new ArrayList<>();
+
+ // Map from the x-value of the left side of a SparseBooleanArray of adapter positions, keyed
+ // by their y-offset. For example, if the first column of the view starts at an x-value of 5,
+ // mColumns.get(5) would return an array of positions in that column. Within that array, the
+ // value for key y is the adapter position for the item whose y-offset is y.
+ private final SparseArray<SparseIntArray> mColumns = new SparseArray<>();
+
+ // List of limits along the x-axis (columns).
+ // This list is sorted from furthest left to furthest right.
+ private final List<Limits> mColumnBounds = new ArrayList<>();
+
+ // List of limits along the y-axis (rows). Note that this list only contains items which
+ // have been in the viewport.
+ private final List<Limits> mRowBounds = new ArrayList<>();
+
+ // The adapter positions which have been recorded so far.
+ private final SparseBooleanArray mKnownPositions = new SparseBooleanArray();
+
+ // Array passed to registered OnSelectionChangedListeners. One array is created and reused
+ // throughout the lifetime of the object.
+ private final Set<String> mSelection = new HashSet<>();
+
+ // The current pointer (in absolute positioning from the top of the view).
+ private Point mPointer = null;
+
+ // The bounds of the band selection.
+ private RelativePoint mRelativeOrigin;
+ private RelativePoint mRelativePointer;
+
+ private boolean mIsActive;
+
+ // Tracks where the band select originated from. This is used to determine where selections
+ // should expand from when Shift+click is used.
+ private int mPositionNearestOrigin = NOT_SET;
+
+ private final OnScrollListener mScrollListener;
+
+ GridModel(
+ BandHost host,
+ StableIdProvider stableIds,
+ SelectionPredicate selectionPredicate) {
+
+ mHost = host;
+ mStableIds = stableIds;
+ mSelectionPredicate = selectionPredicate;
+
+ mScrollListener = new OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ GridModel.this.onScrolled(recyclerView, dx, dy);
+ }
+ };
+
+ mHost.addOnScrollListener(mScrollListener);
+ }
+
+ /**
+ * Stops listening to the view's scrolls. Call this function before discarding a
+ * GridModel object to prevent memory leaks.
+ */
+ void stopListening() {
+ mHost.removeOnScrollListener(mScrollListener);
+ }
+
+ /**
+ * Start a band select operation at the given point.
+ * @param relativeOrigin The origin of the band select operation, relative to the viewport.
+ * For example, if the view is scrolled to the bottom, the top-left of the viewport
+ * would have a relative origin of (0, 0), even though its absolute point has a higher
+ * y-value.
+ */
+ void startCapturing(Point relativeOrigin) {
+ recordVisibleChildren();
+ if (isEmpty()) {
+ // The selection band logic works only if there is at least one visible child.
+ return;
+ }
+
+ mIsActive = true;
+ mPointer = mHost.createAbsolutePoint(relativeOrigin);
+ mRelativeOrigin = new RelativePoint(mPointer);
+ mRelativePointer = new RelativePoint(mPointer);
+ computeCurrentSelection();
+ notifySelectionChanged();
+ }
+
+ /**
+ * Ends the band selection.
+ */
+ void stopCapturing() {
+ mIsActive = false;
+ }
+
+ /**
+ * Resizes the selection by adjusting the pointer (i.e., the corner of the selection
+ * opposite the origin.
+ * @param relativePointer The pointer (opposite of the origin) of the band select operation,
+ * relative to the viewport. For example, if the view is scrolled to the bottom, the
+ * top-left of the viewport would have a relative origin of (0, 0), even though its
+ * absolute point has a higher y-value.
+ */
+ @VisibleForTesting
+ void resizeSelection(Point relativePointer) {
+ mPointer = mHost.createAbsolutePoint(relativePointer);
+ updateModel();
+ }
+
+ /**
+ * @return The adapter position for the item nearest the origin corresponding to the latest
+ * band select operation, or NOT_SET if the selection did not cover any items.
+ */
+ int getPositionNearestOrigin() {
+ return mPositionNearestOrigin;
+ }
+
+ private void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ if (!mIsActive) {
+ return;
+ }
+
+ mPointer.x += dx;
+ mPointer.y += dy;
+ recordVisibleChildren();
+ updateModel();
+ }
+
+ /**
+ * Queries the view for all children and records their location metadata.
+ */
+ private void recordVisibleChildren() {
+ for (int i = 0; i < mHost.getVisibleChildCount(); i++) {
+ int adapterPosition = mHost.getAdapterPositionAt(i);
+ // Sometimes the view is not attached, as we notify the multi selection manager
+ // synchronously, while views are attached asynchronously. As a result items which
+ // are in the adapter may not actually have a corresponding view (yet).
+ if (mHost.hasView(adapterPosition) &&
+ mSelectionPredicate.canSetStateAtPosition(adapterPosition, true) &&
+ !mKnownPositions.get(adapterPosition)) {
+ mKnownPositions.put(adapterPosition, true);
+ recordItemData(mHost.getAbsoluteRectForChildViewAt(i), adapterPosition);
+ }
+ }
+ }
+
+ /**
+ * Checks if there are any recorded children.
+ */
+ private boolean isEmpty() {
+ return mColumnBounds.size() == 0 || mRowBounds.size() == 0;
+ }
+
+ /**
+ * Updates the limits lists and column map with the given item metadata.
+ * @param absoluteChildRect The absolute rectangle for the child view being processed.
+ * @param adapterPosition The position of the child view being processed.
+ */
+ private void recordItemData(Rect absoluteChildRect, int adapterPosition) {
+ if (mColumnBounds.size() != mHost.getColumnCount()) {
+ // If not all x-limits have been recorded, record this one.
+ recordLimits(
+ mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right));
+ }
+
+ recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
+
+ SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
+ if (columnList == null) {
+ columnList = new SparseIntArray();
+ mColumns.put(absoluteChildRect.left, columnList);
+ }
+ columnList.put(absoluteChildRect.top, adapterPosition);
+ }
+
+ /**
+ * Ensures limits exists within the sorted list limitsList, and adds it to the list if it
+ * does not exist.
+ */
+ private void recordLimits(List<Limits> limitsList, Limits limits) {
+ int index = Collections.binarySearch(limitsList, limits);
+ if (index < 0) {
+ limitsList.add(~index, limits);
+ }
+ }
+
+ /**
+ * Handles a moved pointer; this function determines whether the pointer movement resulted
+ * in a selection change and, if it has, notifies listeners of this change.
+ */
+ private void updateModel() {
+ RelativePoint old = mRelativePointer;
+ mRelativePointer = new RelativePoint(mPointer);
+ if (old != null && mRelativePointer.equals(old)) {
+ return;
+ }
+
+ computeCurrentSelection();
+ notifySelectionChanged();
+ }
+
+ /**
+ * Computes the currently-selected items.
+ */
+ private void computeCurrentSelection() {
+ if (areItemsCoveredByBand(mRelativePointer, mRelativeOrigin)) {
+ updateSelection(computeBounds());
+ } else {
+ mSelection.clear();
+ mPositionNearestOrigin = NOT_SET;
+ }
+ }
+
+ /**
+ * Notifies all listeners of a selection change. Note that this function simply passes
+ * mSelection, so computeCurrentSelection() should be called before this
+ * function.
+ */
+ private void notifySelectionChanged() {
+ for (SelectionObserver listener : mOnSelectionChangedListeners) {
+ listener.onSelectionChanged(mSelection);
+ }
+ }
+
+ /**
+ * @param rect Rectangle including all covered items.
+ */
+ private void updateSelection(Rect rect) {
+ int columnStart =
+ Collections.binarySearch(mColumnBounds, new Limits(rect.left, rect.left));
+
+ checkArgument(columnStart >= 0, "Rect doesn't intesect any known column.");
+
+ int columnEnd = columnStart;
+
+ for (int i = columnStart; i < mColumnBounds.size()
+ && mColumnBounds.get(i).lowerLimit <= rect.right; i++) {
+ columnEnd = i;
+ }
+
+ int rowStart = Collections.binarySearch(mRowBounds, new Limits(rect.top, rect.top));
+ if (rowStart < 0) {
+ mPositionNearestOrigin = NOT_SET;
+ return;
+ }
+
+ int rowEnd = rowStart;
+ for (int i = rowStart; i < mRowBounds.size()
+ && mRowBounds.get(i).lowerLimit <= rect.bottom; i++) {
+ rowEnd = i;
+ }
+
+ updateSelection(columnStart, columnEnd, rowStart, rowEnd);
+ }
+
+ /**
+ * Computes the selection given the previously-computed start- and end-indices for each
+ * row and column.
+ */
+ private void updateSelection(
+ int columnStartIndex, int columnEndIndex, int rowStartIndex, int rowEndIndex) {
+
+ if (BandSelectionHelper.DEBUG) {
+ Log.d(BandSelectionHelper.TAG, String.format(
+ "updateSelection: %d, %d, %d, %d",
+ columnStartIndex, columnEndIndex, rowStartIndex, rowEndIndex));
+ }
+
+ mSelection.clear();
+ for (int column = columnStartIndex; column <= columnEndIndex; column++) {
+ SparseIntArray items = mColumns.get(mColumnBounds.get(column).lowerLimit);
+ for (int row = rowStartIndex; row <= rowEndIndex; row++) {
+ // The default return value for SparseIntArray.get is 0, which is a valid
+ // position. Use a sentry value to prevent erroneously selecting item 0.
+ final int rowKey = mRowBounds.get(row).lowerLimit;
+ int position = items.get(rowKey, NOT_SET);
+ if (position != NOT_SET) {
+ String id = mStableIds.getStableId(position);
+ if (id != null) {
+ // The adapter inserts items for UI layout purposes that aren't
+ // associated with files. Those will have a null model ID.
+ // Don't select them.
+ if (canSelect(id)) {
+ mSelection.add(id);
+ }
+ }
+ if (isPossiblePositionNearestOrigin(column, columnStartIndex, columnEndIndex,
+ row, rowStartIndex, rowEndIndex)) {
+ // If this is the position nearest the origin, record it now so that it
+ // can be returned by endSelection() later.
+ mPositionNearestOrigin = position;
+ }
+ }
+ }
+ }
+ }
+
+ private boolean canSelect(String id) {
+ return mSelectionPredicate.canSetStateForId(id, true);
+ }
+
+ /**
+ * @return Returns true if the position is the nearest to the origin, or, in the case of the
+ * lower-right corner, whether it is possible that the position is the nearest to the
+ * origin. See comment below for reasoning for this special case.
+ */
+ private boolean isPossiblePositionNearestOrigin(int columnIndex, int columnStartIndex,
+ int columnEndIndex, int rowIndex, int rowStartIndex, int rowEndIndex) {
+ int corner = computeCornerNearestOrigin();
+ switch (corner) {
+ case UPPER_LEFT:
+ return columnIndex == columnStartIndex && rowIndex == rowStartIndex;
+ case UPPER_RIGHT:
+ return columnIndex == columnEndIndex && rowIndex == rowStartIndex;
+ case LOWER_LEFT:
+ return columnIndex == columnStartIndex && rowIndex == rowEndIndex;
+ case LOWER_RIGHT:
+ // Note that in some cases, the last row will not have as many items as there
+ // are columns (e.g., if there are 4 items and 3 columns, the second row will
+ // only have one item in the first column). This function is invoked for each
+ // position from left to right, so return true for any position in the bottom
+ // row and only the right-most position in the bottom row will be recorded.
+ return rowIndex == rowEndIndex;
+ default:
+ throw new RuntimeException("Invalid corner type.");
+ }
+ }
+
+ /**
+ * Listener for changes in which items have been band selected.
+ */
+ public static abstract class SelectionObserver {
+ abstract void onSelectionChanged(Set<String> updatedSelection);
+ }
+
+ void addOnSelectionChangedListener(SelectionObserver listener) {
+ mOnSelectionChangedListeners.add(listener);
+ }
+
+ /**
+ * Called when {@link BandSelectionHelper} is finished with a GridModel.
+ */
+ void onDestroy() {
+ mOnSelectionChangedListeners.clear();
+ stopListening();
+ }
+
+ /**
+ * Limits of a view item. For example, if an item's left side is at x-value 5 and its right side
+ * is at x-value 10, the limits would be from 5 to 10. Used to record the left- and right sides
+ * of item columns and the top- and bottom sides of item rows so that it can be determined
+ * whether the pointer is located within the bounds of an item.
+ */
+ private static class Limits implements Comparable<Limits> {
+ int lowerLimit;
+ int upperLimit;
+
+ Limits(int lowerLimit, int upperLimit) {
+ this.lowerLimit = lowerLimit;
+ this.upperLimit = upperLimit;
+ }
+
+ @Override
+ public int compareTo(Limits other) {
+ return lowerLimit - other.lowerLimit;
+ }
+
+ @Override
+ public int hashCode() {
+ return lowerLimit ^ upperLimit;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Limits)) {
+ return false;
+ }
+
+ return ((Limits) other).lowerLimit == lowerLimit &&
+ ((Limits) other).upperLimit == upperLimit;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + lowerLimit + ", " + upperLimit + ")";
+ }
+ }
+
+ /**
+ * The location of a coordinate relative to items. This class represents a general area of the
+ * view as it relates to band selection rather than an explicit point. For example, two
+ * different points within an item are considered to have the same "location" because band
+ * selection originating within the item would select the same items no matter which point
+ * was used. Same goes for points between items as well as those at the very beginning or end
+ * of the view.
+ *
+ * Tracking a coordinate (e.g., an x-value) as a CoordinateLocation instead of as an int has the
+ * advantage of tying the value to the Limits of items along that axis. This allows easy
+ * selection of items within those Limits as opposed to a search through every item to see if a
+ * given coordinate value falls within those Limits.
+ */
+ private static class RelativeCoordinate
+ implements Comparable<RelativeCoordinate> {
+ /**
+ * Location describing points after the last known item.
+ */
+ static final int AFTER_LAST_ITEM = 0;
+
+ /**
+ * Location describing points before the first known item.
+ */
+ static final int BEFORE_FIRST_ITEM = 1;
+
+ /**
+ * Location describing points between two items.
+ */
+ static final int BETWEEN_TWO_ITEMS = 2;
+
+ /**
+ * Location describing points within the limits of one item.
+ */
+ static final int WITHIN_LIMITS = 3;
+
+ /**
+ * The type of this coordinate, which is one of AFTER_LAST_ITEM, BEFORE_FIRST_ITEM,
+ * BETWEEN_TWO_ITEMS, or WITHIN_LIMITS.
+ */
+ final int type;
+
+ /**
+ * The limits before the coordinate; only populated when type == WITHIN_LIMITS or type ==
+ * BETWEEN_TWO_ITEMS.
+ */
+ Limits limitsBeforeCoordinate;
+
+ /**
+ * The limits after the coordinate; only populated when type == BETWEEN_TWO_ITEMS.
+ */
+ Limits limitsAfterCoordinate;
+
+ // Limits of the first known item; only populated when type == BEFORE_FIRST_ITEM.
+ Limits mFirstKnownItem;
+ // Limits of the last known item; only populated when type == AFTER_LAST_ITEM.
+ Limits mLastKnownItem;
+
+ /**
+ * @param limitsList The sorted limits list for the coordinate type. If this
+ * CoordinateLocation is an x-value, mXLimitsList should be passed; otherwise,
+ * mYLimitsList should be pased.
+ * @param value The coordinate value.
+ */
+ RelativeCoordinate(List<Limits> limitsList, int value) {
+ int index = Collections.binarySearch(limitsList, new Limits(value, value));
+
+ if (index >= 0) {
+ this.type = WITHIN_LIMITS;
+ this.limitsBeforeCoordinate = limitsList.get(index);
+ } else if (~index == 0) {
+ this.type = BEFORE_FIRST_ITEM;
+ this.mFirstKnownItem = limitsList.get(0);
+ } else if (~index == limitsList.size()) {
+ Limits lastLimits = limitsList.get(limitsList.size() - 1);
+ if (lastLimits.lowerLimit <= value && value <= lastLimits.upperLimit) {
+ this.type = WITHIN_LIMITS;
+ this.limitsBeforeCoordinate = lastLimits;
+ } else {
+ this.type = AFTER_LAST_ITEM;
+ this.mLastKnownItem = lastLimits;
+ }
+ } else {
+ Limits limitsBeforeIndex = limitsList.get(~index - 1);
+ if (limitsBeforeIndex.lowerLimit <= value
+ && value <= limitsBeforeIndex.upperLimit) {
+ this.type = WITHIN_LIMITS;
+ this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+ } else {
+ this.type = BETWEEN_TWO_ITEMS;
+ this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+ this.limitsAfterCoordinate = limitsList.get(~index);
+ }
+ }
+ }
+
+ int toComparisonValue() {
+ if (type == BEFORE_FIRST_ITEM) {
+ return mFirstKnownItem.lowerLimit - 1;
+ } else if (type == AFTER_LAST_ITEM) {
+ return mLastKnownItem.upperLimit + 1;
+ } else if (type == BETWEEN_TWO_ITEMS) {
+ return limitsBeforeCoordinate.upperLimit + 1;
+ } else {
+ return limitsBeforeCoordinate.lowerLimit;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return mFirstKnownItem.lowerLimit
+ ^ mLastKnownItem.upperLimit
+ ^ limitsBeforeCoordinate.upperLimit
+ ^ limitsBeforeCoordinate.lowerLimit;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof RelativeCoordinate)) {
+ return false;
+ }
+
+ RelativeCoordinate otherCoordinate = (RelativeCoordinate) other;
+ return toComparisonValue() == otherCoordinate.toComparisonValue();
+ }
+
+ @Override
+ public int compareTo(RelativeCoordinate other) {
+ return toComparisonValue() - other.toComparisonValue();
+ }
+ }
+
+ /**
+ * The location of a point relative to the Limits of nearby items; consists of both an x- and
+ * y-RelativeCoordinateLocation.
+ */
+ private class RelativePoint {
+ final RelativeCoordinate xLocation;
+ final RelativeCoordinate yLocation;
+
+ RelativePoint(Point point) {
+ this.xLocation = new RelativeCoordinate(mColumnBounds, point.x);
+ this.yLocation = new RelativeCoordinate(mRowBounds, point.y);
+ }
+
+ @Override
+ public int hashCode() {
+ return xLocation.toComparisonValue()
+ ^ yLocation.toComparisonValue();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof RelativePoint)) {
+ return false;
+ }
+
+ RelativePoint otherPoint = (RelativePoint) other;
+ return xLocation.equals(otherPoint.xLocation) && yLocation.equals(otherPoint.yLocation);
+ }
+ }
+
+ /**
+ * Generates a rectangle which contains the items selected by the pointer and origin.
+ * @return The rectangle, or null if no items were selected.
+ */
+ private Rect computeBounds() {
+ Rect rect = new Rect();
+ rect.left = getCoordinateValue(
+ min(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
+ mColumnBounds,
+ true);
+ rect.right = getCoordinateValue(
+ max(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
+ mColumnBounds,
+ false);
+ rect.top = getCoordinateValue(
+ min(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
+ mRowBounds,
+ true);
+ rect.bottom = getCoordinateValue(
+ max(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
+ mRowBounds,
+ false);
+ return rect;
+ }
+
+ /**
+ * Computes the corner of the selection nearest the origin.
+ * @return
+ */
+ private int computeCornerNearestOrigin() {
+ int cornerValue = 0;
+
+ if (mRelativeOrigin.yLocation ==
+ min(mRelativeOrigin.yLocation, mRelativePointer.yLocation)) {
+ cornerValue |= UPPER;
+ } else {
+ cornerValue |= LOWER;
+ }
+
+ if (mRelativeOrigin.xLocation ==
+ min(mRelativeOrigin.xLocation, mRelativePointer.xLocation)) {
+ cornerValue |= LEFT;
+ } else {
+ cornerValue |= RIGHT;
+ }
+
+ return cornerValue;
+ }
+
+ private RelativeCoordinate min(RelativeCoordinate first, RelativeCoordinate second) {
+ return first.compareTo(second) < 0 ? first : second;
+ }
+
+ private RelativeCoordinate max(RelativeCoordinate first, RelativeCoordinate second) {
+ return first.compareTo(second) > 0 ? first : second;
+ }
+
+ /**
+ * @return The absolute coordinate (i.e., the x- or y-value) of the given relative
+ * coordinate.
+ */
+ private int getCoordinateValue(
+ RelativeCoordinate coordinate, List<Limits> limitsList, boolean isStartOfRange) {
+
+ switch (coordinate.type) {
+ case RelativeCoordinate.BEFORE_FIRST_ITEM:
+ return limitsList.get(0).lowerLimit;
+ case RelativeCoordinate.AFTER_LAST_ITEM:
+ return limitsList.get(limitsList.size() - 1).upperLimit;
+ case RelativeCoordinate.BETWEEN_TWO_ITEMS:
+ if (isStartOfRange) {
+ return coordinate.limitsAfterCoordinate.lowerLimit;
+ } else {
+ return coordinate.limitsBeforeCoordinate.upperLimit;
+ }
+ case RelativeCoordinate.WITHIN_LIMITS:
+ return coordinate.limitsBeforeCoordinate.lowerLimit;
+ }
+
+ throw new RuntimeException("Invalid coordinate value.");
+ }
+
+ private boolean areItemsCoveredByBand(
+ RelativePoint first, RelativePoint second) {
+
+ return doesCoordinateLocationCoverItems(first.xLocation, second.xLocation) &&
+ doesCoordinateLocationCoverItems(first.yLocation, second.yLocation);
+ }
+
+ private boolean doesCoordinateLocationCoverItems(
+ RelativeCoordinate pointerCoordinate, RelativeCoordinate originCoordinate) {
+
+ if (pointerCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM &&
+ originCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM) {
+ return false;
+ }
+
+ if (pointerCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM &&
+ originCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM) {
+ return false;
+ }
+
+ if (pointerCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+ originCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+ pointerCoordinate.limitsBeforeCoordinate.equals(
+ originCoordinate.limitsBeforeCoordinate) &&
+ pointerCoordinate.limitsAfterCoordinate.equals(
+ originCoordinate.limitsAfterCoordinate)) {
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/documentsui/selection/ItemDetailsLookup.java b/src/com/android/documentsui/selection/ItemDetailsLookup.java
new file mode 100644
index 0000000..b56a2bc
--- /dev/null
+++ b/src/com/android/documentsui/selection/ItemDetailsLookup.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+
+import javax.annotation.Nullable;
+
+/**
+ * Provides event handlers w/ access to details about documents details
+ * view items Documents in the UI (RecyclerView).
+ */
+public abstract class ItemDetailsLookup {
+
+ /** @return true if there is an item under the finger/cursor. */
+ public abstract boolean overItem(MotionEvent e);
+
+ /** @return true if there is an item w/ a stable ID under the finger/cursor. */
+ public abstract boolean overStableItem(MotionEvent e);
+
+ /**
+ * @return true if the event is over an area that can be dragged via touch
+ * or via mouse. List items have a white area that is not draggable.
+ */
+ public abstract boolean inItemDragRegion(MotionEvent e);
+
+ /**
+ * @return true if the event is in the "selection hot spot" region.
+ * The hot spot region instantly selects in touch mode, vs launches.
+ */
+ public abstract boolean inItemSelectRegion(MotionEvent e);
+
+ /**
+ * @return the adapter position of the item under the finger/cursor.
+ */
+ public abstract int getItemPosition(MotionEvent e);
+
+ /**
+ * @return the DocumentDetails for the item under the event, or null.
+ */
+ public abstract @Nullable ItemDetails getItemDetails(MotionEvent e);
+
+ /**
+ * Abstract class providing helper classes with access to information about
+ * RecyclerView item associated with a MotionEvent.
+ */
+ public static abstract class ItemDetails {
+
+ public boolean hasPosition() {
+ return getPosition() > RecyclerView.NO_POSITION;
+ }
+
+ public abstract int getPosition();
+
+ public boolean hasStableId() {
+ return getStableId() != null;
+ }
+
+ public abstract @Nullable String getStableId();
+
+ /**
+ * @return The view type of this ViewHolder.
+ */
+ public abstract int getItemViewType();
+
+ /**
+ * @return true if the event is in an area of the item that should be
+ * directly interpreted as a user wishing to select the item. This
+ * is useful for checkboxes and other UI affordances focused on enabling
+ * selection.
+ */
+ public boolean inSelectionHotspot(MotionEvent e) {
+ return false;
+ }
+
+ /**
+ * Events in the drag region will not be processed as selection events. This
+ * allows the client to implement custom handling for events related to drag
+ * and drop.
+ */
+ public boolean inDragRegion(MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ItemDetails) {
+ return equals((ItemDetails) obj);
+ }
+ return false;
+ }
+
+ private boolean equals(ItemDetails other) {
+ return this.getPosition() == other.getPosition()
+ && this.getStableId() == other.getStableId();
+ }
+
+ @Override
+ public int hashCode() {
+ return getPosition() >>> 8;
+ }
+ }
+}
diff --git a/src/com/android/documentsui/selection/MotionEvents.java b/src/com/android/documentsui/selection/MotionEvents.java
new file mode 100644
index 0000000..1915c5a
--- /dev/null
+++ b/src/com/android/documentsui/selection/MotionEvents.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import android.graphics.Point;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+/**
+ * Utility methods for working with {@link MotionEvent} instances.
+ */
+final class MotionEvents {
+
+ private MotionEvents() {}
+
+ static boolean isMouseEvent(MotionEvent e) {
+ return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE;
+ }
+
+ static boolean isTouchEvent(MotionEvent e) {
+ return e.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER;
+ }
+
+ static boolean isActionMove(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_MOVE;
+ }
+
+ static boolean isActionDown(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_DOWN;
+ }
+
+ static boolean isActionUp(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_UP;
+ }
+
+ static boolean isActionPointerUp(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_POINTER_UP;
+ }
+
+ static boolean isActionPointerDown(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN;
+ }
+
+ static boolean isActionCancel(MotionEvent e) {
+ return e.getActionMasked() == MotionEvent.ACTION_CANCEL;
+ }
+
+ static Point getOrigin(MotionEvent e) {
+ return new Point((int) e.getX(), (int) e.getY());
+ }
+
+ static boolean isPrimaryButtonPressed(MotionEvent e) {
+ return e.isButtonPressed(MotionEvent.BUTTON_PRIMARY);
+ }
+
+ public static boolean isSecondaryButtonPressed(MotionEvent e) {
+ return e.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
+ }
+
+ public static boolean isTertiaryButtonPressed(MotionEvent e) {
+ return e.isButtonPressed(MotionEvent.BUTTON_TERTIARY);
+ }
+
+ static boolean isShiftKeyPressed(MotionEvent e) {
+ return hasBit(e.getMetaState(), KeyEvent.META_SHIFT_ON);
+ }
+
+ static boolean isCtrlKeyPressed(MotionEvent e) {
+ return hasBit(e.getMetaState(), KeyEvent.META_CTRL_ON);
+ }
+
+ static boolean isAltKeyPressed(MotionEvent e) {
+ return hasBit(e.getMetaState(), KeyEvent.META_ALT_ON);
+ }
+
+ public static boolean isTouchpadScroll(MotionEvent e) {
+ // Touchpad inputs are treated as mouse inputs, and when scrolling, there are no buttons
+ // returned.
+ return isMouseEvent(e) && isActionMove(e) && e.getButtonState() == 0;
+ }
+
+ private static boolean hasBit(int metaState, int bit) {
+ return (metaState & bit) != 0;
+ }
+}
diff --git a/src/com/android/documentsui/selection/MotionInputHandler.java b/src/com/android/documentsui/selection/MotionInputHandler.java
new file mode 100644
index 0000000..474e17d
--- /dev/null
+++ b/src/com/android/documentsui/selection/MotionInputHandler.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+
+/**
+ * Base class for handlers that can be registered w/ {@link GestureRouter}.
+ */
+public abstract class MotionInputHandler extends SimpleOnGestureListener {
+
+ protected final SelectionHelper mSelectionHelper;
+ protected final ItemDetailsLookup mDetailsLookup;
+
+ private final Callbacks mCallbacks;
+
+ public MotionInputHandler(
+ SelectionHelper selectionHelper,
+ ItemDetailsLookup detailsLookup,
+ Callbacks callbacks) {
+
+ checkArgument(selectionHelper != null);
+ checkArgument(detailsLookup != null);
+ checkArgument(callbacks != null);
+
+ mSelectionHelper = selectionHelper;
+ mDetailsLookup = detailsLookup;
+ mCallbacks = callbacks;
+ }
+
+ protected final boolean selectItem(ItemDetails details) {
+ checkArgument(details != null);
+ checkArgument(details.hasPosition());
+ checkArgument(details.hasStableId());
+
+ if (mSelectionHelper.select(details.getStableId())) {
+ mSelectionHelper.anchorRange(details.getPosition());
+ }
+
+ // we set the focus on this doc so it will be the origin for keyboard events or shift+clicks
+ // if there is only a single item selected, otherwise clear focus
+ if (mSelectionHelper.getSelection().size() == 1) {
+ mCallbacks.focusItem(details);
+ } else {
+ mCallbacks.clearFocus();
+ }
+ return true;
+ }
+
+ protected final boolean focusItem(ItemDetails details) {
+ checkArgument(details != null);
+ checkArgument(details.hasStableId());
+
+ mSelectionHelper.clearSelection();
+ mCallbacks.focusItem(details);
+ return true;
+ }
+
+ protected final void extendSelectionRange(ItemDetails details) {
+ checkArgument(details.hasPosition());
+ checkArgument(details.hasStableId());
+
+ mSelectionHelper.extendRange(details.getPosition());
+ mCallbacks.focusItem(details);
+ }
+
+ protected final boolean isRangeExtension(MotionEvent e) {
+ return MotionEvents.isShiftKeyPressed(e) && mSelectionHelper.isRangeActive();
+ }
+
+ protected boolean shouldClearSelection(MotionEvent e, ItemDetails item) {
+ return !MotionEvents.isCtrlKeyPressed(e)
+ && !item.inSelectionHotspot(e)
+ && !mSelectionHelper.isSelected(item.getStableId());
+ }
+
+ public static abstract class Callbacks {
+ public abstract void onPerformHapticFeedback();
+ public void focusItem(ItemDetails item) {}
+ public void clearFocus() {}
+ }
+}
diff --git a/src/com/android/documentsui/selection/MouseInputHandler.java b/src/com/android/documentsui/selection/MouseInputHandler.java
new file mode 100644
index 0000000..7ceb0f5
--- /dev/null
+++ b/src/com/android/documentsui/selection/MouseInputHandler.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import static com.android.documentsui.selection.Shared.DEBUG;
+import static com.android.documentsui.selection.Shared.VERBOSE;
+
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.internal.widget.RecyclerView;
+
+import javax.annotation.Nullable;
+
+/**
+ * A MotionInputHandler that provides the high-level glue for mouse/stylus driven selection. This
+ * class works with {@link RecyclerView}, {@link GestureRouter}, and {@link GestureSelectionHelper}
+ * to provide robust user drive selection support.
+ */
+public final class MouseInputHandler extends MotionInputHandler {
+
+ private static final String TAG = "MouseInputDelegate";
+
+ private final Callbacks mCallbacks;
+
+ // The event has been handled in onSingleTapUp
+ private boolean mHandledTapUp;
+ // true when the previous event has consumed a right click motion event
+ private boolean mHandledOnDown;
+
+ public MouseInputHandler(
+ SelectionHelper selectionHelper,
+ ItemDetailsLookup detailsLookup,
+ Callbacks callbacks) {
+
+ super(selectionHelper, detailsLookup, callbacks);
+
+ mCallbacks = callbacks;
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ if (VERBOSE) Log.v(TAG, "Delegated onDown event.");
+ if ((MotionEvents.isAltKeyPressed(e) && MotionEvents.isPrimaryButtonPressed(e))
+ || MotionEvents.isSecondaryButtonPressed(e)) {
+ mHandledOnDown = true;
+ return onRightClick(e);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ // Don't scroll content window in response to mouse drag
+ // If it's two-finger trackpad scrolling, we want to scroll
+ return !MotionEvents.isTouchpadScroll(e2);
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ // See b/27377794. Since we don't get a button state back from UP events, we have to
+ // explicitly save this state to know whether something was previously handled by
+ // DOWN events or not.
+ if (mHandledOnDown) {
+ if (VERBOSE) Log.v(TAG, "Ignoring onSingleTapUp, previously handled in onDown.");
+ mHandledOnDown = false;
+ return false;
+ }
+
+ if (!mDetailsLookup.overStableItem(e)) {
+ if (DEBUG) Log.d(TAG, "Tap not associated w/ model item. Clearing selection.");
+ mSelectionHelper.clearSelection();
+ mCallbacks.clearFocus();
+ return false;
+ }
+
+ if (MotionEvents.isTertiaryButtonPressed(e)) {
+ if (DEBUG) Log.d(TAG, "Ignoring middle click");
+ return false;
+ }
+
+ ItemDetails item = mDetailsLookup.getItemDetails(e);
+ if (mSelectionHelper.hasSelection()) {
+ if (isRangeExtension(e)) {
+ extendSelectionRange(item);
+ } else {
+ if (shouldClearSelection(e, item)) {
+ mSelectionHelper.clearSelection();
+ }
+ if (mSelectionHelper.isSelected(item.getStableId())) {
+ if (mSelectionHelper.deselect(item.getStableId())) {
+ mCallbacks.clearFocus();
+ }
+ } else {
+ selectOrFocusItem(item, e);
+ }
+ }
+ mHandledTapUp = true;
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (mHandledTapUp) {
+ if (VERBOSE) Log.v(TAG,
+ "Ignoring onSingleTapConfirmed, previously handled in onSingleTapUp.");
+ mHandledTapUp = false;
+ return false;
+ }
+
+ if (mSelectionHelper.hasSelection()) {
+ return false; // should have been handled by onSingleTapUp.
+ }
+
+ if (!mDetailsLookup.overItem(e)) {
+ if (DEBUG) Log.d(TAG, "Ignoring Confirmed Tap on non-item.");
+ return false;
+ }
+
+ if (MotionEvents.isTertiaryButtonPressed(e)) {
+ if (DEBUG) Log.d(TAG, "Ignoring middle click");
+ return false;
+ }
+
+ @Nullable ItemDetails item = mDetailsLookup.getItemDetails(e);
+ if (item == null || !item.hasStableId()) {
+ Log.w(TAG, "Ignoring Confirmed Tap. No document details associated w/ event.");
+ return false;
+ }
+
+ if (mCallbacks.hasFocusedItem() && MotionEvents.isShiftKeyPressed(e)) {
+ mSelectionHelper.startRange(mCallbacks.getFocusedPosition());
+ mSelectionHelper.extendRange(item.getPosition());
+ } else {
+ selectOrFocusItem(item, e);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ mHandledTapUp = false;
+
+ if (!mDetailsLookup.overStableItem(e)) {
+ if (DEBUG) Log.d(TAG, "Ignoring DoubleTap on non-model-backed item.");
+ return false;
+ }
+
+ if (MotionEvents.isTertiaryButtonPressed(e)) {
+ if (DEBUG) Log.d(TAG, "Ignoring middle click");
+ return false;
+ }
+
+ @Nullable ItemDetails item = mDetailsLookup.getItemDetails(e);
+ if (item != null) {
+ return mCallbacks.onItemActivated(item, e);
+ }
+
+ return false;
+ }
+
+ private boolean onRightClick(MotionEvent e) {
+ if (mDetailsLookup.overStableItem(e)) {
+ @Nullable ItemDetails item = mDetailsLookup.getItemDetails(e);
+ if (item != null && !mSelectionHelper.isSelected(item.getStableId())) {
+ mSelectionHelper.clearSelection();
+ selectItem(item);
+ }
+ }
+
+ // We always delegate final handling of the event,
+ // since the handler might want to show a context menu
+ // in an empty area or some other weirdo view.
+ return mCallbacks.onContextClick(e);
+ }
+
+ private void selectOrFocusItem(ItemDetails item, MotionEvent e) {
+ if (item.inSelectionHotspot(e) || MotionEvents.isCtrlKeyPressed(e)) {
+ selectItem(item);
+ } else {
+ focusItem(item);
+ }
+ }
+
+ public static abstract class Callbacks extends MotionInputHandler.Callbacks {
+ public abstract boolean onItemActivated(ItemDetails item, MotionEvent e);
+ public boolean onContextClick(MotionEvent e) {
+ return false;
+ }
+ public boolean hasFocusedItem() {
+ return false;
+ }
+ public int getFocusedPosition() {
+ return RecyclerView.NO_POSITION;
+ }
+ }
+ }
\ No newline at end of file
diff --git a/src/com/android/documentsui/selection/MutableSelection.java b/src/com/android/documentsui/selection/MutableSelection.java
new file mode 100644
index 0000000..7939e14
--- /dev/null
+++ b/src/com/android/documentsui/selection/MutableSelection.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+/**
+ * Subclass of Selection exposing public support for mutating the underlying selection data.
+ * This is useful for clients of {@link SelectionHelper} that wish to manipulate
+ * a copy of selection data obtained via {@link SelectionHelper#copySelection(Selection)}.
+ */
+public final class MutableSelection extends Selection {
+
+ @Override
+ public boolean add(String id) {
+ return super.add(id);
+ }
+
+ @Override
+ public boolean remove(String id) {
+ return super.remove(id);
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ }
+}
diff --git a/src/com/android/documentsui/selection/Range.java b/src/com/android/documentsui/selection/Range.java
index c7db84c..efe49e9 100644
--- a/src/com/android/documentsui/selection/Range.java
+++ b/src/com/android/documentsui/selection/Range.java
@@ -15,36 +15,36 @@
*/
package com.android.documentsui.selection;
-import static com.android.documentsui.base.Shared.DEBUG;
-import static com.android.documentsui.base.Shared.VERBOSE;
+import static android.support.v4.util.Preconditions.checkArgument;
+import static android.support.v7.widget.RecyclerView.NO_POSITION;
+import static com.android.documentsui.selection.Shared.DEBUG;
+import static com.android.documentsui.selection.Shared.TAG;
-import android.support.v7.widget.RecyclerView;
import android.util.Log;
-import com.android.documentsui.selection.SelectionManager.RangeType;
+import com.android.documentsui.selection.DefaultSelectionHelper.RangeType;
/**
* Class providing support for managing range selections.
*/
final class Range {
- private static final int UNDEFINED = -1;
- private final Range.RangeUpdater mUpdater;
+ private final Callbacks mCallbacks;
private final int mBegin;
- private int mEnd = UNDEFINED;
+ private int mEnd = NO_POSITION;
- public Range(Range.RangeUpdater updater, int begin) {
- if (DEBUG) Log.d(SelectionManager.TAG, "New Ranger created beginning @ " + begin);
- mUpdater = updater;
+ public Range(Callbacks callbacks, int begin) {
+ if (DEBUG) Log.d(TAG, "New Ranger created beginning @ " + begin);
+ mCallbacks = callbacks;
mBegin = begin;
}
- void snapSelection(int position, @RangeType int type) {
- assert(position != RecyclerView.NO_POSITION);
+ void extendSelection(int position, @RangeType int type) {
+ checkArgument(position != NO_POSITION, "Position cannot be NO_POSITION.");
- if (mEnd == UNDEFINED || mEnd == mBegin) {
+ if (mEnd == NO_POSITION || mEnd == mBegin) {
// Reset mEnd so it can be established in establishRange.
- mEnd = UNDEFINED;
+ mEnd = NO_POSITION;
establishRange(position, type);
} else {
reviseRange(position, type);
@@ -52,7 +52,7 @@
}
private void establishRange(int position, @RangeType int type) {
- assert(mEnd == UNDEFINED);
+ checkArgument(mEnd == NO_POSITION, "End has already been set.");
if (position == mBegin) {
mEnd = position;
@@ -68,11 +68,11 @@
}
private void reviseRange(int position, @RangeType int type) {
- assert(mEnd != UNDEFINED);
- assert(mBegin != mEnd);
+ checkArgument(mEnd != NO_POSITION, "End must already be set.");
+ checkArgument(mBegin != mEnd, "Beging and end point to same position.");
if (position == mEnd) {
- if (VERBOSE) Log.v(SelectionManager.TAG, "Ignoring no-op revision for range: " + this);
+ if (DEBUG) Log.v(TAG, "Ignoring no-op revision for range: " + this);
}
if (mEnd > mBegin) {
@@ -86,7 +86,7 @@
}
/**
- * Updates an existing ascending seleciton.
+ * Updates an existing ascending selection.
* @param position
*/
private void reviseAscendingRange(int position, @RangeType int type) {
@@ -133,7 +133,7 @@
* @param selected New selection state.
*/
private void updateRange(int begin, int end, boolean selected, @RangeType int type) {
- mUpdater.updateForRange(begin, end, selected, type);
+ mCallbacks.updateForRange(begin, end, selected, type);
}
@Override
@@ -142,11 +142,10 @@
}
/*
- * @see {@link MultiSelectManager#updateForRegularRange(int, int , boolean)} and {@link
- * MultiSelectManager#updateForProvisionalRange(int, int, boolean)}
+ * @see {@link DefaultSelectionHelper#updateForRange(int, int , boolean, int)}.
*/
- @FunctionalInterface
- interface RangeUpdater {
- void updateForRange(int begin, int end, boolean selected, @RangeType int type);
+ static abstract class Callbacks {
+ abstract void updateForRange(
+ int begin, int end, boolean selected, @RangeType int type);
}
}
diff --git a/src/com/android/documentsui/selection/Selection.java b/src/com/android/documentsui/selection/Selection.java
index 8775c58..88b4cbb 100644
--- a/src/com/android/documentsui/selection/Selection.java
+++ b/src/com/android/documentsui/selection/Selection.java
@@ -15,6 +15,8 @@
*/
package com.android.documentsui.selection;
+import static android.support.v4.util.Preconditions.checkArgument;
+
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
@@ -30,22 +32,29 @@
import javax.annotation.Nullable;
/**
- * Object representing the current selection. Provides read only access
- * public access, and private write access.
+ * Object representing the current selection and provisional selection. Provides read only public
+ * access, and private write access.
+ * <p>
+ * This class tracks selected items by managing two sets:
+ *
+ * <li>primary selection
+ *
+ * Primary selection consists of items tapped by a user or by lassoed by band select operation.
+ *
+ * <li>provisional selection
+ *
+ * Provisional selections are selections which have been temporarily created
+ * by an in-progress band select or gesture selection. Once the user releases the mouse button
+ * or lifts their finger the corresponding provisional selection should be converted into
+ * primary selection.
+ *
+ * <p>The total selection is the combination of
+ * both the core selection and the provisional selection. Tracking both separately is necessary to
+ * ensure that items in the core selection are not "erased" from the core selection when they
+ * are temporarily included in a secondary selection (like band selection).
*/
-public final class Selection implements Iterable<String>, Parcelable {
+public class Selection implements Iterable<String>, Parcelable {
- // This class tracks selected items by managing two sets: the saved selection, and the total
- // selection. Saved selections are those which have been completed by tapping an item or by
- // completing a band select operation. Provisional selections are selections which have been
- // temporarily created by an in-progress band select operation (once the user releases the
- // mouse button during a band select operation, the selected items become saved). The total
- // selection is the combination of both the saved selection and the provisional
- // selection. Tracking both separately is necessary to ensure that saved selections do not
- // become deselected when they are removed from the provisional selection; for example, if
- // item A is tapped (and selected), then an in-progress band select covers A then uncovers
- // A, A should still be selected as it has been saved. To ensure this behavior, the saved
- // selection must be tracked separately.
final Set<String> mSelection;
final Set<String> mProvisionalSelection;
@@ -101,13 +110,12 @@
* one (if it exists) is abandoned.
* @return Map of ids added or removed. Added ids have a value of true, removed are false.
*/
- @VisibleForTesting
- protected Map<String, Boolean> setProvisionalSelection(Set<String> newSelection) {
+ Map<String, Boolean> setProvisionalSelection(Set<String> newSelection) {
Map<String, Boolean> delta = new HashMap<>();
for (String id: mProvisionalSelection) {
- // Mark each item that used to be in the selection but is unsaved and not in the new
- // provisional selection.
+ // Mark each item that used to be in the provisional selection
+ // but is not in the new provisional selection.
if (!newSelection.contains(id) && !mSelection.contains(id)) {
delta.put(id, false);
}
@@ -150,7 +158,7 @@
* cause items in this existing provisional selection to become deselected.
*/
@VisibleForTesting
- protected void applyProvisionalSelection() {
+ protected void mergeProvisionalSelection() {
mSelection.addAll(mProvisionalSelection);
mProvisionalSelection.clear();
}
@@ -160,42 +168,59 @@
* now deselected.
*/
@VisibleForTesting
- void cancelProvisionalSelection() {
+ void clearProvisionalSelection() {
mProvisionalSelection.clear();
}
- /** @hide */
- @VisibleForTesting
- public boolean add(String id) {
- if (!mSelection.contains(id)) {
- mSelection.add(id);
- return true;
- }
- return false;
- }
-
- /** @hide */
- @VisibleForTesting
- boolean remove(String id) {
+ /**
+ * Adds a new item to the primary selection.
+ *
+ * @return true if the operation resulted in a modification to the selection.
+ */
+ boolean add(String id) {
if (mSelection.contains(id)) {
- mSelection.remove(id);
- return true;
+ return false;
}
- return false;
+
+ mSelection.add(id);
+ return true;
}
- public void clear() {
+ /**
+ * Removes an item from the primary selection.
+ *
+ * @return true if the operation resulted in a modification to the selection.
+ */
+ boolean remove(String id) {
+ if (!mSelection.contains(id)) {
+ return false;
+ }
+
+ mSelection.remove(id);
+ return true;
+ }
+
+ /**
+ * Clears the primary selection. The provisional selection, if any, is unaffected.
+ */
+ void clear() {
mSelection.clear();
}
/**
- * Trims this selection to be the intersection of itself with the set of given IDs.
+ * Trims this selection to be the intersection of itself and {@code ids}.
*/
- public void intersect(Collection<String> ids) {
+ void intersect(Collection<String> ids) {
+ checkArgument(ids != null);
+
mSelection.retainAll(ids);
mProvisionalSelection.retainAll(ids);
}
+ /**
+ * Clones primary and provisional selection from supplied {@link Selection}.
+ * Does not copy active range data.
+ */
@VisibleForTesting
void copyFrom(Selection source) {
mSelection.clear();
@@ -213,7 +238,7 @@
StringBuilder buffer = new StringBuilder(size() * 28);
buffer.append("Selection{")
- .append("applied{size=" + mSelection.size())
+ .append("primary{size=" + mSelection.size())
.append(", entries=" + mSelection)
.append("}, provisional{size=" + mProvisionalSelection.size())
.append(", entries=" + mProvisionalSelection)
@@ -227,17 +252,19 @@
}
@Override
- public boolean equals(Object that) {
- if (this == that) {
- return true;
- }
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
- if (!(that instanceof Selection)) {
- return false;
- }
+ return other instanceof Selection
+ ? equals((Selection) other)
+ : false;
+ }
- return mSelection.equals(((Selection) that).mSelection) &&
- mProvisionalSelection.equals(((Selection) that).mProvisionalSelection);
+ private boolean equals(Selection other) {
+ return mSelection.equals(((Selection) other).mSelection) &&
+ mProvisionalSelection.equals(((Selection) other).mProvisionalSelection);
}
@Override
diff --git a/src/com/android/documentsui/selection/SelectionHelper.java b/src/com/android/documentsui/selection/SelectionHelper.java
new file mode 100644
index 0000000..bd8b34e
--- /dev/null
+++ b/src/com/android/documentsui/selection/SelectionHelper.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * SelectionManager provides support for managing selection within a RecyclerView instance.
+ *
+ * @see DefaultSelectionHelper for details on instantiation.
+ */
+public abstract class SelectionHelper {
+
+ /**
+ * This value is included in the payload when SelectionHelper implementations
+ * notify RecyclerView of changes. Clients can look for this in
+ * {@code onBindViewHolder} to know if the bind event is occurring in response
+ * to a selection state change.
+ */
+ public static final String SELECTION_CHANGED_MARKER = "Selection-Changed";
+
+ /**
+ * Adds {@code observe} to be notified when changes to selection occur.
+ *
+ * @param observer
+ */
+ public abstract void addObserver(SelectionObserver observer);
+
+ public abstract boolean hasSelection();
+
+ /**
+ * Returns a Selection object that provides a live view on the current selection.
+ *
+ * @see #copySelection(Selection) on how to get a snapshot
+ * of the selection that will not reflect future changes
+ * to selection.
+ *
+ * @return The current selection.
+ */
+ public abstract Selection getSelection();
+
+ /**
+ * Updates {@code dest} to reflect the current selection.
+ * @param dest
+ */
+ public abstract void copySelection(Selection dest);
+
+ /**
+ * @return true if the item specified by its id is selected. Shorthand for
+ * {@code getSelection().contains(String)}.
+ */
+ public abstract boolean isSelected(String id);
+
+ /**
+ * Restores the selected state of specified items. Used in cases such as restore the selection
+ * after rotation etc. Provisional selection, being provisional 'n all, isn't restored.
+ */
+ public abstract void restoreSelection(Selection other);
+
+ /**
+ * Sets the selected state of the specified items. Note that the callback will NOT
+ * be consulted to see if an item can be selected.
+ *
+ * @param ids
+ * @param selected
+ * @return
+ */
+ public abstract boolean setItemsSelected(Iterable<String> ids, boolean selected);
+
+ /**
+ * Clears the selection and notifies (if something changes).
+ */
+ public abstract void clearSelection();
+
+ /**
+ * Attempts to select an item.
+ *
+ * @return true if the item was selected. False if the item was not selected, or was
+ * was already selected prior to the method being called.
+ */
+ public abstract boolean select(String itemId);
+
+ /**
+ * Attempts to deselect an item.
+ *
+ * @return true if the item was deselected. False if the item was not deselected, or was
+ * was already deselected prior to the method being called.
+ */
+ public abstract boolean deselect(String itemId);
+
+ /**
+ * Starts a range selection. If a range selection is already active, this will start a new range
+ * selection (which will reset the range anchor).
+ *
+ * @param pos The anchor position for the selection range.
+ */
+ public abstract void startRange(int pos);
+
+ /**
+ * Sets the end point for the active range selection.
+ *
+ * <p>This function should only be called when a range selection is active
+ * (see {@link #isRangeActive()}. Items in the range [anchor, end] will be
+ * selected.
+ *
+ * @param pos The new end position for the selection range.
+ * @param type The type of selection the range should utilize.
+ *
+ * @throws IllegalStateException if a range selection is not active. Range selection
+ * must have been started by a call to {@link #startRange(int)}.
+ */
+ public abstract void extendRange(int pos);
+
+ /**
+ * Stops an in-progress range selection. All selection done with
+ * {@link #extendProvisionalRange(int)} will be lost if
+ * {@link Selection#mergeProvisionalSelection()} is not called beforehand.
+ */
+ public abstract void endRange();
+
+ /**
+ * @return Whether or not there is a current range selection active.
+ */
+ public abstract boolean isRangeActive();
+
+ /**
+ * Sets the magic location at which a selection range begins (the selection anchor). This value
+ * is consulted when determining how to extend, and modify selection ranges. Calling this when a
+ * range selection is active will reset the range selection.
+ */
+ public abstract void anchorRange(int position);
+
+ /**
+ * @param pos
+ */
+ // TODO: This is smelly. Maybe this type of logic needs to move into range selection,
+ // then selection manager can have a startProvisionalRange and startRange. Or
+ // maybe ranges always start life as provisional.
+ public abstract void extendProvisionalRange(int pos);
+
+ /**
+ * @param newSelection
+ */
+ public abstract void setProvisionalSelection(Set<String> newSelection);
+
+ /**
+ *
+ */
+ public abstract void clearProvisionalSelection();
+
+ public abstract void mergeProvisionalSelection();
+
+ /**
+ * Observer interface providing access to information about Selection state changes.
+ */
+ public static abstract class SelectionObserver {
+
+ /**
+ * Called when state of an item has been changed.
+ */
+ public void onItemStateChanged(String id, boolean selected) {}
+
+ /**
+ * Called when the underlying data set has change. After this method is called
+ * the selection manager will attempt traverse the existing selection,
+ * calling {@link #onItemStateChanged(String, boolean)} for each selected item,
+ * and deselecting any items that cannot be selected given the updated dataset.
+ */
+ public void onSelectionReset() {}
+
+ /**
+ * Called immediately after completion of any set of changes, excluding
+ * those resulting in calls to {@link #onSelectionReset()} and
+ * {@link #onSelectionRestored()}.
+ */
+ public void onSelectionChanged() {}
+
+ /**
+ * Called immediately after selection is restored.
+ * {@link #onItemStateChanged(String, boolean)} will not be called
+ * for individual items in the selection.
+ */
+ public void onSelectionRestored() {}
+ }
+
+ /**
+ * Facilitates the use of stable ids.
+ */
+ public static abstract class StableIdProvider {
+ /**
+ * @return The model ID of the item at the given adapter position.
+ */
+ public abstract String getStableId(int position);
+
+ /**
+ * @return the position of a stable ID, or RecyclerView.NO_POSITION.
+ */
+ public abstract int getPosition(String id);
+
+ /**
+ * @return A list of all known stable IDs.
+ */
+ public abstract List<String> getStableIds();
+ }
+
+ /**
+ * Implement SelectionPredicate to control when items can be selected or unselected.
+ */
+ public static abstract class SelectionPredicate {
+
+ /** @return true if the item at {@code id} can be set to {@code nextState}. */
+ public abstract boolean canSetStateForId(String id, boolean nextState);
+
+ /** @return true if the item at {@code id} can be set to {@code nextState}. */
+ public abstract boolean canSetStateAtPosition(int position, boolean nextState);
+
+ /** @return true if more than a single item can be selected. */
+ public boolean canSelectMultiple() {
+ return true;
+ }
+ }
+}
diff --git a/src/com/android/documentsui/selection/SelectionManager.java b/src/com/android/documentsui/selection/SelectionManager.java
deleted file mode 100644
index af77cfa..0000000
--- a/src/com/android/documentsui/selection/SelectionManager.java
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import static com.android.documentsui.base.Shared.DEBUG;
-
-import android.annotation.IntDef;
-import android.support.annotation.VisibleForTesting;
-import android.support.v7.widget.RecyclerView;
-import android.util.Log;
-
-import com.android.documentsui.dirlist.DocumentsAdapter;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-/**
- * MultiSelectManager provides support traditional multi-item selection support to RecyclerView.
- * Additionally it can be configured to restrict selection to a single element, @see
- * #setSelectMode.
- */
-public final class SelectionManager {
-
- @IntDef(flag = true, value = {
- MODE_MULTIPLE,
- MODE_SINGLE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SelectionMode {}
- public static final int MODE_MULTIPLE = 0;
- public static final int MODE_SINGLE = 1;
-
- @IntDef({
- RANGE_REGULAR,
- RANGE_PROVISIONAL
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface RangeType {}
- public static final int RANGE_REGULAR = 0;
- public static final int RANGE_PROVISIONAL = 1;
-
- static final String TAG = "SelectionManager";
-
- private final Selection mSelection = new Selection();
-
- private final List<Callback> mCallbacks = new ArrayList<>(1);
- private final List<ItemCallback> mItemCallbacks = new ArrayList<>(1);
-
- private @Nullable DocumentsAdapter mAdapter;
- private @Nullable Range mRanger;
- private boolean mSingleSelect;
-
- private RecyclerView.AdapterDataObserver mAdapterObserver;
- private SelectionPredicate mCanSetState;
-
- public SelectionManager(@SelectionMode int mode) {
- mSingleSelect = mode == MODE_SINGLE;
- }
-
- public SelectionManager reset(DocumentsAdapter adapter, SelectionPredicate canSetState) {
-
- mCallbacks.clear();
- mItemCallbacks.clear();
- if (mAdapter != null && mAdapterObserver != null) {
- mAdapter.unregisterAdapterDataObserver(mAdapterObserver);
- }
-
- clearSelectionQuietly();
-
- assert(adapter != null);
- assert(canSetState != null);
-
- mAdapter = adapter;
- mCanSetState = canSetState;
-
- mAdapterObserver = new RecyclerView.AdapterDataObserver() {
-
- private List<String> mModelIds;
-
- @Override
- public void onChanged() {
- mModelIds = mAdapter.getModelIds();
-
- // Update the selection to remove any disappeared IDs.
- mSelection.cancelProvisionalSelection();
- mSelection.intersect(mModelIds);
-
- notifyDataChanged();
- }
-
- @Override
- public void onItemRangeChanged(
- int startPosition, int itemCount, Object payload) {
- // No change in position. Ignoring.
- }
-
- @Override
- public void onItemRangeInserted(int startPosition, int itemCount) {
- mSelection.cancelProvisionalSelection();
- }
-
- @Override
- public void onItemRangeRemoved(int startPosition, int itemCount) {
- assert(startPosition >= 0);
- assert(itemCount > 0);
-
- mSelection.cancelProvisionalSelection();
- // Remove any disappeared IDs from the selection.
- mSelection.intersect(mModelIds);
- }
-
- @Override
- public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
- throw new UnsupportedOperationException();
- }
- };
-
- mAdapter.registerAdapterDataObserver(mAdapterObserver);
- return this;
- }
-
- void bindContoller(BandController controller) {
- // Provides BandController with access to private mSelection state.
- controller.bindSelection(mSelection);
- }
-
- /**
- * Adds {@code callback} such that it will be notified when {@code MultiSelectManager}
- * events occur.
- *
- * @param callback
- */
- public void addCallback(Callback callback) {
- assert(callback != null);
- mCallbacks.add(callback);
- }
-
- public void addItemCallback(ItemCallback itemCallback) {
- assert(itemCallback != null);
- mItemCallbacks.add(itemCallback);
- }
-
- public boolean hasSelection() {
- return !mSelection.isEmpty();
- }
-
- /**
- * Returns a Selection object that provides a live view
- * on the current selection.
- *
- * @see #getSelection(Selection) on how to get a snapshot
- * of the selection that will not reflect future changes
- * to selection.
- *
- * @return The current selection.
- */
- public Selection getSelection() {
- return mSelection;
- }
-
- /**
- * Updates {@code dest} to reflect the current selection.
- * @param dest
- *
- * @return The Selection instance passed in, for convenience.
- */
- public Selection getSelection(Selection dest) {
- dest.copyFrom(mSelection);
- return dest;
- }
-
- @VisibleForTesting
- public void replaceSelection(Iterable<String> ids) {
- clearSelection();
- setItemsSelected(ids, true);
- }
-
- /**
- * Restores the selected state of specified items. Used in cases such as restore the selection
- * after rotation etc.
- */
- public void restoreSelection(Selection other) {
- setItemsSelectedQuietly(other.mSelection, true);
- // NOTE: We intentionally don't restore provisional selection. It's provisional.
- notifySelectionRestored();
- }
-
- /**
- * Sets the selected state of the specified items. Note that the callback will NOT
- * be consulted to see if an item can be selected.
- *
- * @param ids
- * @param selected
- * @return
- */
- public boolean setItemsSelected(Iterable<String> ids, boolean selected) {
- final boolean changed = setItemsSelectedQuietly(ids, selected);
- notifySelectionChanged();
- return changed;
- }
-
- private boolean setItemsSelectedQuietly(Iterable<String> ids, boolean selected) {
- boolean changed = false;
- for (String id: ids) {
- final boolean itemChanged =
- selected
- ? canSetState(id, true) && mSelection.add(id)
- : canSetState(id, false) && mSelection.remove(id);
- if (itemChanged) {
- notifyItemStateChanged(id, selected);
- }
- changed |= itemChanged;
- }
- return changed;
- }
-
- /**
- * Clears the selection and notifies (if something changes).
- */
- public void clearSelection() {
- if (!hasSelection()) {
- return;
- }
-
- clearSelectionQuietly();
- notifySelectionChanged();
- }
-
- /**
- * Clears the selection, without notifying selection listeners. UI elements still need to be
- * notified about state changes so that they can update their appearance.
- */
- private void clearSelectionQuietly() {
- mRanger = null;
-
- if (!hasSelection()) {
- return;
- }
-
- Selection oldSelection = getSelection(new Selection());
- mSelection.clear();
-
- for (String id: oldSelection.mSelection) {
- notifyItemStateChanged(id, false);
- }
- for (String id: oldSelection.mProvisionalSelection) {
- notifyItemStateChanged(id, false);
- }
- }
-
- /**
- * Toggles selection on the item with the given model ID.
- *
- * @param modelId
- */
- public void toggleSelection(String modelId) {
- assert(modelId != null);
-
- final boolean changed = mSelection.contains(modelId)
- ? attemptDeselect(modelId)
- : attemptSelect(modelId);
-
- if (changed) {
- notifySelectionChanged();
- }
- }
-
- /**
- * Starts a range selection. If a range selection is already active, this will start a new range
- * selection (which will reset the range anchor).
- *
- * @param pos The anchor position for the selection range.
- */
- public void startRangeSelection(int pos) {
- attemptSelect(mAdapter.getModelId(pos));
- setSelectionRangeBegin(pos);
- }
-
- public void snapRangeSelection(int pos) {
- snapRangeSelection(pos, RANGE_REGULAR);
- }
-
- void snapProvisionalRangeSelection(int pos) {
- snapRangeSelection(pos, RANGE_PROVISIONAL);
- }
-
- /*
- * Starts and extends range selection in one go. This assumes item at startPos is not selected
- * beforehand.
- */
- public void formNewSelectionRange(int startPos, int endPos) {
- assert(!mSelection.contains(mAdapter.getModelId(startPos)));
- startRangeSelection(startPos);
- snapRangeSelection(endPos);
- }
-
- /**
- * Sets the end point for the current range selection, started by a call to
- * {@link #startRangeSelection(int)}. This function should only be called when a range selection
- * is active (see {@link #isRangeSelectionActive()}. Items in the range [anchor, end] will be
- * selected or in provisional select, depending on the type supplied. Note that if the type is
- * provisional select, one should do {@link Selection#applyProvisionalSelection()} at some point
- * before calling on {@link #endRangeSelection()}.
- *
- * @param pos The new end position for the selection range.
- * @param type The type of selection the range should utilize.
- */
- private void snapRangeSelection(int pos, @RangeType int type) {
- if (!isRangeSelectionActive()) {
- throw new IllegalStateException("Range start point not set.");
- }
-
- mRanger.snapSelection(pos, type);
-
- // We're being lazy here notifying even when something might not have changed.
- // To make this more correct, we'd need to update the Ranger class to return
- // information about what has changed.
- notifySelectionChanged();
- }
-
- void cancelProvisionalSelection() {
- for (String id : mSelection.mProvisionalSelection) {
- notifyItemStateChanged(id, false);
- }
- mSelection.cancelProvisionalSelection();
- }
-
- /**
- * Stops an in-progress range selection. All selection done with
- * {@link #snapRangeSelection(int, int)} with type RANGE_PROVISIONAL will be lost if
- * {@link Selection#applyProvisionalSelection()} is not called beforehand.
- */
- public void endRangeSelection() {
- mRanger = null;
- // Clean up in case there was any leftover provisional selection
- cancelProvisionalSelection();
- }
-
- /**
- * @return Whether or not there is a current range selection active.
- */
- public boolean isRangeSelectionActive() {
- return mRanger != null;
- }
-
- /**
- * Sets the magic location at which a selection range begins (the selection anchor). This value
- * is consulted when determining how to extend, and modify selection ranges. Calling this when a
- * range selection is active will reset the range selection.
- */
- public void setSelectionRangeBegin(int position) {
- if (position == RecyclerView.NO_POSITION) {
- return;
- }
-
- if (mSelection.contains(mAdapter.getModelId(position))) {
- mRanger = new Range(this::updateForRange, position);
- }
- }
-
- /**
- * @param modelId
- * @return True if the update was applied.
- */
- private boolean selectAndNotify(String modelId) {
- boolean changed = mSelection.add(modelId);
- if (changed) {
- notifyItemStateChanged(modelId, true);
- }
- return changed;
- }
-
- /**
- * @param id
- * @return True if the update was applied.
- */
- private boolean attemptDeselect(String id) {
- assert(id != null);
- if (canSetState(id, false)) {
- mSelection.remove(id);
- notifyItemStateChanged(id, false);
-
- // if there's nothing in the selection and there is an active ranger it results
- // in unexpected behavior when the user tries to start range selection: the item
- // which the ranger 'thinks' is the already selected anchor becomes unselectable
- if (mSelection.isEmpty() && isRangeSelectionActive()) {
- endRangeSelection();
- }
- if (DEBUG) Log.d(TAG, "Selection after deselect: " + mSelection);
- return true;
- } else {
- if (DEBUG) Log.d(TAG, "Select cancelled by listener.");
- return false;
- }
- }
-
- /**
- * @param id
- * @return True if the update was applied.
- */
- private boolean attemptSelect(String id) {
- assert(id != null);
- boolean canSelect = canSetState(id, true);
- if (!canSelect) {
- return false;
- }
- if (mSingleSelect && hasSelection()) {
- clearSelectionQuietly();
- }
-
- selectAndNotify(id);
- return true;
- }
-
- boolean canSetState(String id, boolean nextState) {
- return mCanSetState.test(id, nextState);
- }
-
- private void notifyDataChanged() {
- final int lastListener = mItemCallbacks.size() - 1;
-
- for (int i = lastListener; i >= 0; i--) {
- mItemCallbacks.get(i).onSelectionReset();
- }
-
- for (String id : mSelection) {
- if (!canSetState(id, true)) {
- attemptDeselect(id);
- } else {
- for (int i = lastListener; i >= 0; i--) {
- mItemCallbacks.get(i).onItemStateChanged(id, true);
- }
- }
- }
- }
-
- /**
- * Notifies registered listeners when the selection status of a single item
- * (identified by {@code position}) changes.
- */
- void notifyItemStateChanged(String id, boolean selected) {
- assert(id != null);
- int lastListener = mItemCallbacks.size() - 1;
- for (int i = lastListener; i >= 0; i--) {
- mItemCallbacks.get(i).onItemStateChanged(id, selected);
- }
- mAdapter.onItemSelectionChanged(id);
- }
-
- /**
- * Notifies registered listeners when the selection has changed. This
- * notification should be sent only once a full series of changes
- * is complete, e.g. clearingSelection, or updating the single
- * selection from one item to another.
- */
- void notifySelectionChanged() {
- int lastListener = mCallbacks.size() - 1;
- for (int i = lastListener; i > -1; i--) {
- mCallbacks.get(i).onSelectionChanged();
- }
- }
-
- private void notifySelectionRestored() {
- int lastListener = mCallbacks.size() - 1;
- for (int i = lastListener; i > -1; i--) {
- mCallbacks.get(i).onSelectionRestored();
- }
- }
-
- void updateForRange(int begin, int end, boolean selected, @RangeType int type) {
- switch (type) {
- case RANGE_REGULAR:
- updateForRegularRange(begin, end, selected);
- break;
- case RANGE_PROVISIONAL:
- updateForProvisionalRange(begin, end, selected);
- break;
- default:
- throw new IllegalArgumentException("Invalid range type: " + type);
- }
- }
-
- private void updateForRegularRange(int begin, int end, boolean selected) {
- assert(end >= begin);
- for (int i = begin; i <= end; i++) {
- String id = mAdapter.getModelId(i);
- if (id == null) {
- continue;
- }
-
- if (selected) {
- boolean canSelect = canSetState(id, true);
- if (canSelect) {
- if (mSingleSelect && hasSelection()) {
- clearSelectionQuietly();
- }
- selectAndNotify(id);
- }
- } else {
- attemptDeselect(id);
- }
- }
- }
-
- private void updateForProvisionalRange(int begin, int end, boolean selected) {
- assert (end >= begin);
- for (int i = begin; i <= end; i++) {
- String id = mAdapter.getModelId(i);
- if (id == null) {
- continue;
- }
-
- boolean changedState = false;
- if (selected) {
- boolean canSelect = canSetState(id, true);
- if (canSelect && !mSelection.mSelection.contains(id)) {
- mSelection.mProvisionalSelection.add(id);
- changedState = true;
- }
- } else {
- mSelection.mProvisionalSelection.remove(id);
- changedState = true;
- }
-
- // Only notify item callbacks when something's state is actually changed in provisional
- // selection.
- if (changedState) {
- notifyItemStateChanged(id, selected);
- }
- }
- notifySelectionChanged();
- }
-
- public interface ItemCallback {
- void onItemStateChanged(String id, boolean selected);
-
- void onSelectionReset();
- }
-
- public interface Callback {
- /**
- * Called immediately after completion of any set of changes.
- */
- void onSelectionChanged();
-
- /**
- * Called immediately after selection is restored.
- */
- void onSelectionRestored();
- }
-
- @FunctionalInterface
- public interface SelectionPredicate {
- boolean test(String id, boolean nextState);
- }
-}
diff --git a/src/com/android/documentsui/selection/Shared.java b/src/com/android/documentsui/selection/Shared.java
new file mode 100644
index 0000000..bf30919
--- /dev/null
+++ b/src/com/android/documentsui/selection/Shared.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+/**
+ * Shared constants used in this and descendant packages.
+ */
+public final class Shared {
+
+ public static final String TAG = "SelectionHelper";
+ public static final boolean DEBUG = false;
+ public static final boolean VERBOSE = false;
+
+ private Shared() {}
+}
diff --git a/src/com/android/documentsui/selection/ToolHandlerRegistry.java b/src/com/android/documentsui/selection/ToolHandlerRegistry.java
new file mode 100644
index 0000000..65f9f2e
--- /dev/null
+++ b/src/com/android/documentsui/selection/ToolHandlerRegistry.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+import static android.support.v4.util.Preconditions.checkState;
+
+import android.support.annotation.Nullable;
+import android.view.MotionEvent;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Registry for tool specific event handler.
+ */
+final class ToolHandlerRegistry<T> {
+
+ // Currently there are four known input types. ERASER is the last one, so has the
+ // highest value. UNKNOWN is zero, so we add one. This allows delegates to be
+ // registered by type, and avoid the auto-boxing that would be necessary were we
+ // to store delegates in a Map<Integer, Delegate>.
+ private static final int sNumInputTypes = MotionEvent.TOOL_TYPE_ERASER + 1;
+
+ private final List<T> mHandlers = Arrays.asList(null, null, null, null, null);
+ private final T mDefault;
+
+ ToolHandlerRegistry(T defaultDelegate) {
+ checkArgument(defaultDelegate != null);
+ mDefault = defaultDelegate;
+
+ // Initialize all values to null.
+ for (int i = 0; i < sNumInputTypes; i++) {
+ mHandlers.set(i, null);
+ }
+ }
+
+ /**
+ * @param toolType
+ * @param delegate the delegate, or null to unregister.
+ * @throws IllegalStateException if an tooltype handler is already registered.
+ */
+ void set(int toolType, @Nullable T delegate) {
+ checkArgument(toolType >= 0 && toolType <= MotionEvent.TOOL_TYPE_ERASER);
+ checkState(mHandlers.get(toolType) == null);
+
+ mHandlers.set(toolType, delegate);
+ }
+
+ T get(MotionEvent e) {
+ T d = mHandlers.get(e.getToolType(0));
+ return d != null ? d : mDefault;
+ }
+}
diff --git a/src/com/android/documentsui/selection/TouchEventRouter.java b/src/com/android/documentsui/selection/TouchEventRouter.java
new file mode 100644
index 0000000..50585fe
--- /dev/null
+++ b/src/com/android/documentsui/selection/TouchEventRouter.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+/**
+ * A class responsible for routing MotionEvents to tool-type specific handlers,
+ * and if not handled by a handler, on to a {@link GestureDetector} for further
+ * processing.
+ *
+ * <p>TouchEventRouter takes its name from
+ * {@link RecyclerView#addOnItemTouchListener(OnItemTouchListener)}. Despite "Touch"
+ * being in the name, it receives MotionEvents for all types of tools.
+ */
+public final class TouchEventRouter implements OnItemTouchListener {
+
+ private final GestureDetector mDetector;
+ private final ToolHandlerRegistry<OnItemTouchListener> mDelegates;
+
+ public TouchEventRouter(GestureDetector detector, OnItemTouchListener defaultDelegate) {
+ checkArgument(detector != null);
+ checkArgument(defaultDelegate != null);
+
+ mDetector = detector;
+ mDelegates = new ToolHandlerRegistry<>(defaultDelegate);
+ }
+
+ public TouchEventRouter(GestureDetector detector) {
+ this(
+ detector,
+ // Default listener does nothing.
+ new OnItemTouchListener() {
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ }
+ });
+ }
+
+ /**
+ * @param toolType See MotionEvent for details on available types.
+ * @param delegate An {@link OnItemTouchListener} to receive events
+ * of {@code toolType}.
+ */
+ public void register(int toolType, OnItemTouchListener delegate) {
+ checkArgument(delegate != null);
+ mDelegates.set(toolType, delegate);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ boolean handled = mDelegates.get(e).onInterceptTouchEvent(rv, e);
+
+ // Forward all events to UserInputHandler.
+ // This is necessary since UserInputHandler needs to always see the first DOWN event. Or
+ // else all future UP events will be tossed.
+ handled |= mDetector.onTouchEvent(e);
+
+ return handled;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ mDelegates.get(e).onTouchEvent(rv, e);
+
+ // Note: even though this event is being handled as part of gestures such as drag and band,
+ // continue forwarding to the GestureDetector. The detector needs to see the entire cluster
+ // of events in order to properly interpret other gestures, such as long press.
+ mDetector.onTouchEvent(e);
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+}
diff --git a/src/com/android/documentsui/selection/TouchInputHandler.java b/src/com/android/documentsui/selection/TouchInputHandler.java
new file mode 100644
index 0000000..12ed33c
--- /dev/null
+++ b/src/com/android/documentsui/selection/TouchInputHandler.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import static com.android.documentsui.base.Shared.DEBUG;
+
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+/**
+ * A MotionInputHandler that provides the high-level glue for touch driven selection. This class
+ * works with {@link RecyclerView}, {@link GestureRouter}, and {@link GestureSelectionHelper} to
+ * provide robust user drive selection support.
+ */
+public final class TouchInputHandler extends MotionInputHandler {
+ private static final String TAG = "TouchInputDelegate";
+
+ private final SelectionPredicate mSelectionPredicate;
+ private final Callbacks mCallbacks;
+ private final Runnable mGestureKicker;
+
+ public TouchInputHandler(
+ SelectionHelper selectionHelper,
+ ItemDetailsLookup detailsLookup,
+ SelectionPredicate selectionPredicate,
+ Runnable gestureKicker,
+ Callbacks callbacks) {
+
+ super(selectionHelper, detailsLookup, callbacks);
+
+ mSelectionPredicate = selectionPredicate;
+ mGestureKicker = gestureKicker;
+ mCallbacks = callbacks;
+ }
+
+ public TouchInputHandler(
+ SelectionHelper selectionHelper,
+ ItemDetailsLookup detailsLookup,
+ SelectionPredicate selectionPredicate,
+ GestureSelectionHelper gestureHelper,
+ Callbacks callbacks) {
+
+ this(
+ selectionHelper,
+ detailsLookup,
+ selectionPredicate,
+ new Runnable() {
+ @Override
+ public void run() {
+ gestureHelper.start();
+ }
+ },
+ callbacks);
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ if (!mDetailsLookup.overStableItem(e)) {
+ if (DEBUG) Log.d(TAG, "Tap not associated w/ model item. Clearing selection.");
+ mSelectionHelper.clearSelection();
+ return false;
+ }
+
+ ItemDetails item = mDetailsLookup.getItemDetails(e);
+ if (mSelectionHelper.hasSelection()) {
+ if (isRangeExtension(e)) {
+ extendSelectionRange(item);
+ } else if (mSelectionHelper.isSelected(item.getStableId())) {
+ mSelectionHelper.deselect(item.getStableId());
+ } else {
+ selectItem(item);
+ }
+
+ return true;
+ }
+
+ // Touch events select if they occur in the selection hotspot,
+ // otherwise they activate.
+ return item.inSelectionHotspot(e)
+ ? selectItem(item)
+ : mCallbacks.onItemActivated(item, e);
+ }
+
+ @Override
+ public final void onLongPress(MotionEvent e) {
+ if (!mDetailsLookup.overStableItem(e)) {
+ if (DEBUG) Log.d(TAG, "Ignoring LongPress on non-model-backed item.");
+ return;
+ }
+
+ ItemDetails item = mDetailsLookup.getItemDetails(e);
+ boolean handled = false;
+
+ if (isRangeExtension(e)) {
+ extendSelectionRange(item);
+ handled = true;
+ } else {
+ if (!mSelectionHelper.isSelected(item.getStableId())
+ && mSelectionPredicate.canSetStateForId(item.getStableId(), true)) {
+ // If we cannot select it, we didn't apply anchoring - therefore should not
+ // start gesture selection
+ if (selectItem(item)) {
+ // And finally if the item was selected && we can select multiple
+ // we kick off gesture selection.
+ if (mSelectionPredicate.canSelectMultiple()) {
+ mGestureKicker.run();
+ }
+ handled = true;
+ }
+ } else {
+ // We only initiate drag and drop on long press for touch to allow regular
+ // touch-based scrolling
+ // mTouchDragListener.accept(e);
+ mCallbacks.onDragInitiated(e);
+ handled = true;
+ }
+ }
+
+ if (handled) {
+ mCallbacks.onPerformHapticFeedback();
+ }
+ }
+
+ public static abstract class Callbacks extends MotionInputHandler.Callbacks {
+ public abstract boolean onItemActivated(ItemDetails item, MotionEvent e);
+ public boolean onDragInitiated(MotionEvent e) {
+ return false;
+ }
+ }
+}
diff --git a/src/com/android/documentsui/ui/ViewAutoScroller.java b/src/com/android/documentsui/selection/ViewAutoScroller.java
similarity index 74%
rename from src/com/android/documentsui/ui/ViewAutoScroller.java
rename to src/com/android/documentsui/selection/ViewAutoScroller.java
index 2add5ae..b77176c 100644
--- a/src/com/android/documentsui/ui/ViewAutoScroller.java
+++ b/src/com/android/documentsui/selection/ViewAutoScroller.java
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-
-package com.android.documentsui.ui;
+package com.android.documentsui.selection;
import android.graphics.Point;
@@ -27,19 +26,20 @@
* past top/bottom of the screen.
*/
public final class ViewAutoScroller implements Runnable {
- public static final int NOT_SET = -1;
+
// ratio used to calculate the top/bottom hotspot region; used with view height
public static final float TOP_BOTTOM_THRESHOLD_RATIO = 0.125f;
public static final int MAX_SCROLL_STEP = 70;
- // Top and bottom inner buffer such that user's cursor does not have to be exactly off screen
- // for auto scrolling to begin
- private final ScrollDistanceDelegate mCalcDelegate;
- private final ScrollActionDelegate mUiDelegate;
+ private ScrollHost mHost;
+ private ScrollerCallbacks mCallbacks;
- public ViewAutoScroller(ScrollDistanceDelegate calcDelegate, ScrollActionDelegate uiDelegate) {
- mCalcDelegate = calcDelegate;
- mUiDelegate = uiDelegate;
+ public ViewAutoScroller(ScrollHost scrollHost, ScrollerCallbacks callbacks) {
+ assert scrollHost != null;
+ assert callbacks != null;
+
+ mHost = scrollHost;
+ mCallbacks = callbacks;
}
/**
@@ -56,18 +56,18 @@
// pointer are in these buffer pixels.
int pixelsPastView = 0;
- final int topBottomThreshold = (int) (mCalcDelegate.getViewHeight()
+ final int topBottomThreshold = (int) (mHost.getViewHeight()
* TOP_BOTTOM_THRESHOLD_RATIO);
- if (mCalcDelegate.getCurrentPosition().y <= topBottomThreshold) {
- pixelsPastView = mCalcDelegate.getCurrentPosition().y - topBottomThreshold;
- } else if (mCalcDelegate.getCurrentPosition().y >= mCalcDelegate.getViewHeight()
+ if (mHost.getCurrentPosition().y <= topBottomThreshold) {
+ pixelsPastView = mHost.getCurrentPosition().y - topBottomThreshold;
+ } else if (mHost.getCurrentPosition().y >= mHost.getViewHeight()
- topBottomThreshold) {
- pixelsPastView = mCalcDelegate.getCurrentPosition().y - mCalcDelegate.getViewHeight()
+ pixelsPastView = mHost.getCurrentPosition().y - mHost.getViewHeight()
+ topBottomThreshold;
}
- if (!mCalcDelegate.isActive() || pixelsPastView == 0) {
+ if (!mHost.isActive() || pixelsPastView == 0) {
// If the operation that started the scrolling is no longer inactive, or if it is active
// but not at the edge of the view, no scrolling is necessary.
return;
@@ -79,11 +79,11 @@
// Compute the number of pixels to scroll, and scroll that many pixels.
final int numPixels = computeScrollDistance(pixelsPastView);
- mUiDelegate.scrollBy(numPixels);
+ mCallbacks.scrollBy(numPixels);
// Remove callback to this, and then properly run at next frame again
- mUiDelegate.removeCallback(this);
- mUiDelegate.runAtNextFrame(this);
+ mCallbacks.removeCallback(this);
+ mCallbacks.runAtNextFrame(this);
}
/**
@@ -93,8 +93,8 @@
* @return
*/
public int computeScrollDistance(int pixelsPastView) {
- final int topBottomThreshold = (int) (mCalcDelegate.getViewHeight()
- * TOP_BOTTOM_THRESHOLD_RATIO);
+ final int topBottomThreshold =
+ (int) (mHost.getViewHeight() * TOP_BOTTOM_THRESHOLD_RATIO);
final int direction = (int) Math.signum(pixelsPastView);
final int absPastView = Math.abs(pixelsPastView);
@@ -131,18 +131,19 @@
* Used by {@link run} to properly calculate the proper amount of pixels to scroll given time
* passed since scroll started, and to properly scroll / proper listener clean up if necessary.
*/
- public interface ScrollDistanceDelegate {
- public Point getCurrentPosition();
- public int getViewHeight();
- public boolean isActive();
+ public static abstract class ScrollHost {
+ public abstract Point getCurrentPosition();
+ public abstract int getViewHeight();
+ public abstract boolean isActive();
}
/**
- * Used by {@link run} to do UI tasks, such as scrolling and rerunning at next UI cycle.
+ * Callback used by scroller to perform UI tasks, such as scrolling and rerunning at next UI
+ * cycle.
*/
- public interface ScrollActionDelegate {
- public void scrollBy(int dy);
- public void runAtNextFrame(Runnable r);
- public void removeCallback(Runnable r);
+ public static abstract class ScrollerCallbacks {
+ public void scrollBy(int dy) {}
+ public void runAtNextFrame(Runnable r) {}
+ public void removeCallback(Runnable r) {}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/documentsui/selection/demo/DemoDetailsLookup.java b/src/com/android/documentsui/selection/demo/DemoDetailsLookup.java
new file mode 100644
index 0000000..6811125
--- /dev/null
+++ b/src/com/android/documentsui/selection/demo/DemoDetailsLookup.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.demo;
+
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.documentsui.selection.ItemDetailsLookup;
+
+/**
+ * Access to details of an item associated with a {@link MotionEvent} instance.
+ */
+final class DemoDetailsLookup extends ItemDetailsLookup {
+
+ private final RecyclerView mRecView;
+
+ public DemoDetailsLookup(RecyclerView view) {
+ mRecView = view;
+ }
+
+ @Override
+ public boolean overItem(MotionEvent e) {
+ return getItemPosition(e) != RecyclerView.NO_POSITION;
+ }
+
+ @Override
+ public boolean overStableItem(MotionEvent e) {
+ return overItem(e) && getItemDetails(e).hasStableId();
+ }
+
+ @Override
+ public boolean inItemDragRegion(MotionEvent e) {
+ return overItem(e) && getItemDetails(e).inDragRegion(e);
+ }
+
+ @Override
+ public boolean inItemSelectRegion(MotionEvent e) {
+ return overItem(e) && getItemDetails(e).inSelectionHotspot(e);
+ }
+
+ @Override
+ public int getItemPosition(MotionEvent e) {
+ View child = mRecView.findChildViewUnder(e.getX(), e.getY());
+ return (child != null)
+ ? mRecView.getChildAdapterPosition(child)
+ : RecyclerView.NO_POSITION;
+ }
+
+ @Override
+ public ItemDetails getItemDetails(MotionEvent e) {
+ @Nullable DemoHolder holder = getDemoHolder(e);
+ return holder == null ? null : holder.getItemDetails();
+ }
+
+ private @Nullable DemoHolder getDemoHolder(MotionEvent e) {
+ View childView = mRecView.findChildViewUnder(e.getX(), e.getY());
+ if (childView != null) {
+ ViewHolder holder = mRecView.getChildViewHolder(childView);
+ if (holder instanceof DemoHolder) {
+ return (DemoHolder) holder;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/documentsui/selection/demo/DemoHolder.java b/src/com/android/documentsui/selection/demo/DemoHolder.java
new file mode 100644
index 0000000..3a783b5
--- /dev/null
+++ b/src/com/android/documentsui/selection/demo/DemoHolder.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.demo;
+
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.documentsui.R;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+
+public final class DemoHolder extends RecyclerView.ViewHolder {
+
+ private final LinearLayout mContainer;
+ public final TextView mSelector;
+ public final TextView mLabel;
+ private final Details mDetails;
+ private DemoItem mItem;
+
+ DemoHolder(LinearLayout layout) {
+ super(layout);
+ mContainer = layout.findViewById(R.id.container);
+ mSelector = layout.findViewById(R.id.selector);
+ mLabel = layout.findViewById(R.id.label);
+ mDetails = new Details(this);
+ }
+
+ public void update(DemoItem demoItem) {
+ mItem = demoItem;
+ mLabel.setText(mItem.getName());
+ }
+
+ void setSelected(boolean selected) {
+ mContainer.setActivated(selected);
+ mSelector.setActivated(selected);
+ }
+
+ public String getStableId() {
+ return mItem != null ? mItem.getId() : null;
+ }
+
+ public boolean inDragRegion(MotionEvent e) {
+ // If itemView is activated = selected, then whole region is interactive
+ if (mContainer.isActivated()) {
+ return true;
+ }
+
+ if (inSelectRegion(e)) {
+ return true;
+ }
+
+ Rect rect = new Rect();
+ mLabel.getPaint().getTextBounds(
+ mLabel.getText().toString(), 0, mLabel.getText().length(), rect);
+
+ // If the tap occurred inside the text, these are interactive spots.
+ return rect.contains((int) e.getRawX(), (int) e.getRawY());
+ }
+
+ public boolean inSelectRegion(MotionEvent e) {
+ Rect iconRect = new Rect();
+ mSelector.getGlobalVisibleRect(iconRect);
+ return iconRect.contains((int) e.getRawX(), (int) e.getRawY());
+ }
+
+ Details getItemDetails() {
+ return mDetails;
+ }
+
+ private static final class Details extends ItemDetails {
+
+ private final DemoHolder mHolder;
+
+ Details(DemoHolder holder) {
+ mHolder = holder;
+ }
+
+ @Override
+ public int getPosition() {
+ return mHolder.getAdapterPosition();
+ }
+
+ @Override
+ public String getStableId() {
+ return mHolder.getStableId();
+ }
+
+ @Override
+ public int getItemViewType() {
+ return mHolder.getItemViewType();
+ }
+
+ @Override
+ public boolean inDragRegion(MotionEvent e) {
+ return mHolder.inDragRegion(e);
+ }
+
+ @Override
+ public boolean inSelectionHotspot(MotionEvent e) {
+ return mHolder.inSelectRegion(e);
+ }
+ }
+ }
\ No newline at end of file
diff --git a/src/com/android/documentsui/selection/demo/DemoItem.java b/src/com/android/documentsui/selection/demo/DemoItem.java
new file mode 100644
index 0000000..15755a0
--- /dev/null
+++ b/src/com/android/documentsui/selection/demo/DemoItem.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.demo;
+
+public class DemoItem {
+
+ private final String mId;
+ private final String mName;
+
+ DemoItem(String id, String name) {
+ mId = id;
+ mName = name;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public String getName() {
+ return mName;
+ }
+}
diff --git a/src/com/android/documentsui/selection/demo/DemoStableIdProvider.java b/src/com/android/documentsui/selection/demo/DemoStableIdProvider.java
new file mode 100644
index 0000000..45cdd6c
--- /dev/null
+++ b/src/com/android/documentsui/selection/demo/DemoStableIdProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.demo;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import com.android.documentsui.selection.SelectionHelper.StableIdProvider;
+
+import java.util.List;
+
+/**
+ * Provides RecyclerView selection code access to stable ids backed
+ * by DocumentsAdapter.
+ */
+final class DemoStableIdProvider extends StableIdProvider {
+
+ private final SelectionDemoAdapter mAdapter;
+
+ public DemoStableIdProvider(SelectionDemoAdapter adapter) {
+ checkArgument(adapter != null);
+ mAdapter = adapter;
+ }
+
+ @Override
+ public String getStableId(int position) {
+ return mAdapter.getStableId(position);
+ }
+
+ @Override
+ public int getPosition(String id) {
+ return mAdapter.getPosition(id);
+ }
+
+ @Override
+ public List<String> getStableIds() {
+ return mAdapter.getStableIds();
+ }
+}
diff --git a/src/com/android/documentsui/selection/demo/SelectionDemoActivity.java b/src/com/android/documentsui/selection/demo/SelectionDemoActivity.java
new file mode 100644
index 0000000..6d348a8
--- /dev/null
+++ b/src/com/android/documentsui/selection/demo/SelectionDemoActivity.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection.demo;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.CallSuper;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.Toolbar;
+import android.view.GestureDetector;
+import android.view.HapticFeedbackConstants;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.widget.Toast;
+
+import com.android.documentsui.R;
+import com.android.documentsui.selection.BandSelectionHelper;
+import com.android.documentsui.selection.ContentLock;
+import com.android.documentsui.selection.DefaultBandHost;
+import com.android.documentsui.selection.DefaultBandPredicate;
+import com.android.documentsui.selection.DefaultSelectionHelper;
+import com.android.documentsui.selection.GestureRouter;
+import com.android.documentsui.selection.GestureSelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.documentsui.selection.MotionInputHandler;
+import com.android.documentsui.selection.MouseInputHandler;
+import com.android.documentsui.selection.MutableSelection;
+import com.android.documentsui.selection.Selection;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+import com.android.documentsui.selection.SelectionHelper.StableIdProvider;
+import com.android.documentsui.selection.TouchEventRouter;
+import com.android.documentsui.selection.TouchInputHandler;
+import com.android.documentsui.selection.demo.SelectionDemoAdapter.OnBindCallback;
+
+/**
+ * ContentPager demo activity.
+ */
+public class SelectionDemoActivity extends AppCompatActivity {
+
+ private static final String EXTRA_SAVED_SELECTION = "demo-saved-selection";
+ private static final String EXTRA_COLUMN_COUNT = "demo-column-count";
+
+ private Toolbar mToolbar;
+ private SelectionDemoAdapter mAdapter;
+ private SelectionHelper mSelectionHelper;
+
+ private RecyclerView mRecView;
+ private GridLayoutManager mLayout;
+ private int mColumnCount = 1; // This will get updated when layout changes.
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.selection_demo_layout);
+ mToolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(mToolbar);
+ mRecView = (RecyclerView) findViewById(R.id.list);
+
+ mLayout = new GridLayoutManager(this, mColumnCount);
+ mRecView.setLayoutManager(mLayout);
+
+ mAdapter = new SelectionDemoAdapter(this);
+ mRecView.setAdapter(mAdapter);
+
+ StableIdProvider stableIds = new DemoStableIdProvider(mAdapter);
+
+ // SelectionPredicate permits client control of which items can be selected.
+ SelectionPredicate canSelectAnything = new SelectionPredicate() {
+ @Override
+ public boolean canSetStateForId(String id, boolean nextState) {
+ return true;
+ }
+
+ @Override
+ public boolean canSetStateAtPosition(int position, boolean nextState) {
+ return true;
+ }
+ };
+
+ // TODO: Reload content when it changes. Could use CursorLoader.
+ // TODO: Retain selection. Restore when content changes.
+
+ mSelectionHelper = new DefaultSelectionHelper(
+ DefaultSelectionHelper.MODE_MULTIPLE,
+ mAdapter,
+ stableIds,
+ canSelectAnything);
+
+ // onBind event callback that allows items to be updated to reflect
+ // selection status when bound by recycler view.
+ // This allows us to defer initialization of the SelectionHelper dependency
+ // which itself depends on the Adapter.
+ mAdapter.addOnBindCallback(
+ new OnBindCallback() {
+ @Override
+ void onBound(DemoHolder holder, int position) {
+ String id = mAdapter.getStableId(position);
+ holder.setSelected(mSelectionHelper.isSelected(id));
+ }
+ });
+
+ ItemDetailsLookup detailsLookup = new DemoDetailsLookup(mRecView);
+
+ // Setup basic input handling, with the touch handler as the default consumer
+ // of events. If mouse handling is configured as well, the mouse input
+ // related handlers will intercept mouse input events.
+
+ // GestureRouter is responsible for routing GestureDetector events
+ // to tool-type specific handlers.
+ GestureRouter<MotionInputHandler> gestureRouter = new GestureRouter<>();
+ GestureDetector gestureDetector = new GestureDetector(this, gestureRouter);
+
+ // TouchEventRouter takes its name from RecyclerView#OnItemTouchListener.
+ // Despite "Touch" being in the name, it receives events for all types of tools.
+ // This class is responsible for routing events to tool-type specific handlers,
+ // and if not handled by a handler, on to a GestureDetector for analysis.
+ TouchEventRouter eventRouter = new TouchEventRouter(gestureDetector);
+
+ // Content lock provides a mechanism to block content reload while selection
+ // activities are active. If using a loader to load content, route
+ // the call through the content lock using ContentLock#runWhenUnlocked.
+ // This is especially useful when listening on content change notification.
+ ContentLock contentLock = new ContentLock();
+
+ // GestureSelectionHelper provides logic that interprets a combination
+ // of motions and gestures in order to provide gesture driven selection support
+ // when used in conjunction with RecyclerView.
+ GestureSelectionHelper gestureHelper =
+ GestureSelectionHelper.create(mSelectionHelper, mRecView, contentLock);
+
+ // Finally hook the framework up to listening to recycle view events.
+ mRecView.addOnItemTouchListener(eventRouter);
+
+ // But before you move on, there's more work to do. Event plumbing has been
+ // installed, but we haven't registered any of our helpers or callbacks.
+ // Helpers contain predefined logic converting events into selection related events.
+ // Callbacks provide authors the ability to reponspond to other types of
+ // events (like "active" a tapped item). This is broken up into two main
+ // suites, one for "touch" and one for "mouse", though both can and should (usually)
+ // be configued to handle other types of input (to satisfy user expectation).
+
+ // TOUCH (+ UNKNOWN) handeling provides gesture based selection allowing
+ // the user to long press on an item, then drag her finger over other
+ // items in order to extend the selection.
+ TouchCallbacks touchCallbacks = new TouchCallbacks(this, mRecView);
+
+ // Provides high level glue for binding touch events and gestures to selection framework.
+ TouchInputHandler touchHandler = new TouchInputHandler(
+ mSelectionHelper, detailsLookup, canSelectAnything, gestureHelper, touchCallbacks);
+
+ eventRouter.register(MotionEvent.TOOL_TYPE_FINGER, gestureHelper);
+ eventRouter.register(MotionEvent.TOOL_TYPE_UNKNOWN, gestureHelper);
+
+ gestureRouter.register(MotionEvent.TOOL_TYPE_FINGER, touchHandler);
+ gestureRouter.register(MotionEvent.TOOL_TYPE_UNKNOWN, touchHandler);
+
+ // MOUSE (+ STYLUS) handeling provides band based selection allowing
+ // the user to click down in an empty area, then drag her mouse
+ // to create a band that covers the items she wants selected.
+ //
+ // PRO TIP: Don't skip installing mouse/stylus support. It provides
+ // improved productivity and demonstrates feature maturity that users
+ // will appreciate. See InputManager for details on more sophisticated
+ // strategies on detecting the presence of input tools.
+
+ // Provides high level glue for binding mouse/stylus events and gestures
+ // to selection framework.
+ MouseInputHandler mouseHandler = new MouseInputHandler(
+ mSelectionHelper, detailsLookup, new MouseCallbacks(this, mRecView));
+
+ DefaultBandHost host = new DefaultBandHost(
+ mRecView, R.drawable.selection_demo_band_overlay);
+
+ // BandSelectionHelper provides support for band selection on-top of a RecyclerView
+ // instance. Given the recycling nature of RecyclerView BandSelectionController
+ // necessarily models and caches list/grid information as the user's pointer
+ // interacts with the item in the RecyclerView. Selectable items that intersect
+ // with the band, both on and off screen, are selected.
+ BandSelectionHelper bandHelper = new BandSelectionHelper(
+ host,
+ mAdapter,
+ stableIds,
+ mSelectionHelper,
+ canSelectAnything,
+ new DefaultBandPredicate(detailsLookup),
+ contentLock);
+
+
+ eventRouter.register(MotionEvent.TOOL_TYPE_MOUSE, bandHelper);
+ eventRouter.register(MotionEvent.TOOL_TYPE_STYLUS, bandHelper);
+
+ gestureRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mouseHandler);
+ gestureRouter.register(MotionEvent.TOOL_TYPE_STYLUS, mouseHandler);
+
+ // Aaaaan, all done with mouse/stylus selection setup!
+
+ updateFromSavedState(savedInstanceState);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle state) {
+ super.onSaveInstanceState(state);
+ MutableSelection selection = new MutableSelection();
+ mSelectionHelper.copySelection(selection);
+ state.putParcelable(EXTRA_SAVED_SELECTION, selection);
+ state.putInt(EXTRA_COLUMN_COUNT, mColumnCount);
+ }
+
+ private void updateFromSavedState(Bundle state) {
+ // In order to preserve selection across various lifecycle events be sure to save
+ // the selection in onSaveInstanceState, and to restore it when present in the Bundle
+ // pass in via onCreate(Bundle).
+ if (state != null) {
+ if (state.containsKey(EXTRA_SAVED_SELECTION)) {
+ Selection savedSelection = state.getParcelable(EXTRA_SAVED_SELECTION);
+ if (!savedSelection.isEmpty()) {
+ mSelectionHelper.restoreSelection(savedSelection);
+ CharSequence text = "Selection restored.";
+ Toast.makeText(this, "Selection restored.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ if (state.containsKey(EXTRA_COLUMN_COUNT)) {
+ mColumnCount = state.getInt(EXTRA_COLUMN_COUNT);
+ mLayout.setSpanCount(mColumnCount);
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ boolean showMenu = super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.selection_demo_actions, menu);
+ return showMenu;
+ }
+
+ @Override
+ @CallSuper
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ menu.findItem(R.id.option_menu_add_column).setEnabled(mColumnCount <= 3);
+ menu.findItem(R.id.option_menu_remove_column).setEnabled(mColumnCount > 1);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.option_menu_add_column:
+ // TODO: Add columns
+ mLayout.setSpanCount(++mColumnCount);
+ return true;
+
+ case R.id.option_menu_remove_column:
+ mLayout.setSpanCount(--mColumnCount);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+
+ @Override
+ public void onBackPressed () {
+ if (mSelectionHelper.hasSelection()) {
+ mSelectionHelper.clearSelection();
+ mSelectionHelper.clearProvisionalSelection();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ private static void toast(Context context, String msg) {
+ Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ protected void onDestroy() {
+ mSelectionHelper.clearSelection();
+ super.onDestroy();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mAdapter.loadData();
+ }
+
+ // Implementation of MouseInputHandler.Callbacks allows handling
+ // of higher level events, like onActivated.
+ private static final class MouseCallbacks extends MouseInputHandler.Callbacks {
+
+ private final Context mContext;
+ private final RecyclerView mRecView;
+
+ MouseCallbacks(Context context, RecyclerView recView) {
+ mContext = context;
+ mRecView = recView;
+ }
+
+ @Override
+ public boolean onItemActivated(ItemDetails item, MotionEvent e) {
+ toast(mContext, "Activate item: " + item.getStableId());
+ return true;
+ }
+
+ @Override
+ public boolean onContextClick(MotionEvent e) {
+ toast(mContext, "Context click received.");
+ return true;
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+ };
+
+ private static final class TouchCallbacks extends TouchInputHandler.Callbacks {
+
+ private final Context mContext;
+ private final RecyclerView mRecView;
+
+ private TouchCallbacks(Context context, RecyclerView recView) {
+
+ mContext = context;
+ mRecView = recView;
+ }
+
+ @Override
+ public boolean onItemActivated(ItemDetails item, MotionEvent e) {
+ toast(mContext, "Activate item: " + item.getStableId());
+ return true;
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/documentsui/selection/demo/SelectionDemoAdapter.java b/src/com/android/documentsui/selection/demo/SelectionDemoAdapter.java
new file mode 100644
index 0000000..b896e91
--- /dev/null
+++ b/src/com/android/documentsui/selection/demo/SelectionDemoAdapter.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.demo;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.documentsui.R;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+final class SelectionDemoAdapter extends RecyclerView.Adapter<DemoHolder> {
+
+ private static final Map<String, DemoItem> sDemoData = new HashMap<>();
+ static {
+ for (int i = 0; i < 1000; i++) {
+ String id = createId(i);
+ sDemoData.put(id, new DemoItem(id, "item" + i));
+ }
+ }
+
+ private final Context mContext;
+ private @Nullable OnBindCallback mBindCallback;
+
+ SelectionDemoAdapter(Context context) {
+ mContext = context;
+ }
+
+ void addOnBindCallback(OnBindCallback bindCallback) {
+ mBindCallback = bindCallback;
+ }
+
+ void loadData() {
+ onDataReady();
+ }
+
+ private void onDataReady() {
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getItemCount() {
+ return sDemoData.size();
+ }
+
+ @Override
+ public void onBindViewHolder(DemoHolder holder, int position) {
+ String id = createId(position);
+ holder.update(sDemoData.get(id));
+ if (mBindCallback != null) {
+ mBindCallback.onBound(holder, position);
+ }
+ }
+
+ private static String createId(int position) {
+ return "id" + position;
+ }
+
+ @Override
+ public DemoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ LinearLayout layout = inflateLayout(mContext, parent, R.layout.selection_demo_list_item);
+ return new DemoHolder(layout);
+ }
+
+ String getStableId(int position) {
+ return createId(position);
+ }
+
+ int getPosition(String id) {
+ return Integer.parseInt(id.substring(2));
+ }
+
+ List<String> getStableIds() {
+ return new ArrayList<>(sDemoData.keySet());
+ }
+
+ @SuppressWarnings("TypeParameterUnusedInFormals") // Convenience to avoid clumsy cast.
+ private static <V extends View> V inflateLayout(
+ Context context, ViewGroup parent, int layout) {
+
+ return (V) LayoutInflater.from(context).inflate(layout, parent, false);
+ }
+
+ static abstract class OnBindCallback {
+ abstract void onBound(DemoHolder holder, int position);
+ }
+}
diff --git a/src/com/android/documentsui/services/FileOperation.java b/src/com/android/documentsui/services/FileOperation.java
index 2ee12d5..1f0e9b9 100644
--- a/src/com/android/documentsui/services/FileOperation.java
+++ b/src/com/android/documentsui/services/FileOperation.java
@@ -16,12 +16,13 @@
package com.android.documentsui.services;
-import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
import static com.android.documentsui.services.FileOperationService.OPERATION_COMPRESS;
-import static com.android.documentsui.services.FileOperationService.OPERATION_EXTRACT;
+import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE;
+import static com.android.documentsui.services.FileOperationService.OPERATION_EXTRACT;
import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
+import static com.android.internal.util.Preconditions.checkArgument;
import android.content.Context;
import android.net.Uri;
@@ -57,8 +58,8 @@
@VisibleForTesting
FileOperation(@OpType int opType, UrisSupplier srcs, DocumentStack destination) {
- assert(opType != OPERATION_UNKNOWN);
- assert(srcs.getItemCount() > 0);
+ checkArgument(opType != OPERATION_UNKNOWN);
+ checkArgument(srcs.getItemCount() > 0);
mOpType = opType;
mSrcs = srcs;
@@ -133,6 +134,7 @@
return builder.toString();
}
+ @Override
CopyJob createJob(Context service, Job.Listener listener, String id, Features features) {
return new CopyJob(
service, listener, id, getDestination(), getSrc(), getMessenger(), features);
@@ -173,6 +175,7 @@
return builder.toString();
}
+ @Override
CopyJob createJob(Context service, Job.Listener listener, String id, Features features) {
return new CompressJob(service, listener, id, getDestination(), getSrc(),
getMessenger(), features);
@@ -214,6 +217,7 @@
}
// TODO: Replace CopyJob with ExtractJob.
+ @Override
CopyJob createJob(Context service, Job.Listener listener, String id, Features features) {
return new CopyJob(
service, listener, id, getDestination(), getSrc(), getMessenger(), features);
diff --git a/src/com/android/documentsui/services/FileOperationService.java b/src/com/android/documentsui/services/FileOperationService.java
index 6379237..046722e 100644
--- a/src/com/android/documentsui/services/FileOperationService.java
+++ b/src/com/android/documentsui/services/FileOperationService.java
@@ -354,7 +354,7 @@
job.id, NOTIFICATION_ID_PROGRESS, notification);
// Set up related monitor
- JobMonitor monitor = new JobMonitor(job, notificationManager, handler);
+ JobMonitor monitor = new JobMonitor(job, notificationManager, handler, mJobs);
monitor.start();
}
@@ -458,11 +458,14 @@
private final Job mJob;
private final NotificationManager mNotificationManager;
private final Handler mHandler;
+ private final Object mJobsLock;
- private JobMonitor(Job job, NotificationManager notificationManager, Handler handler) {
+ private JobMonitor(Job job, NotificationManager notificationManager, Handler handler,
+ Object jobsLock) {
mJob = job;
mNotificationManager = notificationManager;
mHandler = handler;
+ mJobsLock = jobsLock;
}
private void start() {
@@ -471,19 +474,21 @@
@Override
public void run() {
- if (mJob.isFinished()) {
- // Finish notification is already shown. Progress notification is removed.
- // Just finish itself.
- return;
- }
+ synchronized (mJobsLock) {
+ if (mJob.isFinished()) {
+ // Finish notification is already shown. Progress notification is removed.
+ // Just finish itself.
+ return;
+ }
- // Only job in set up state has progress bar
- if (mJob.getState() == Job.STATE_SET_UP) {
- mNotificationManager.notify(
- mJob.id, NOTIFICATION_ID_PROGRESS, mJob.getProgressNotification());
- }
+ // Only job in set up state has progress bar
+ if (mJob.getState() == Job.STATE_SET_UP) {
+ mNotificationManager.notify(
+ mJob.id, NOTIFICATION_ID_PROGRESS, mJob.getProgressNotification());
+ }
- mHandler.postDelayed(this, PROGRESS_INTERVAL_MILLIS);
+ mHandler.postDelayed(this, PROGRESS_INTERVAL_MILLIS);
+ }
}
}
diff --git a/src/com/android/documentsui/services/Job.java b/src/com/android/documentsui/services/Job.java
index 25ed4de..0605e53 100644
--- a/src/com/android/documentsui/services/Job.java
+++ b/src/com/android/documentsui/services/Job.java
@@ -172,8 +172,7 @@
return true;
}
- void finish() {
- }
+ abstract void finish();
abstract void start();
abstract Notification getSetupNotification();
diff --git a/src/com/android/documentsui/ui/Snackbars.java b/src/com/android/documentsui/ui/Snackbars.java
index 8fa84dc..933af97 100644
--- a/src/com/android/documentsui/ui/Snackbars.java
+++ b/src/com/android/documentsui/ui/Snackbars.java
@@ -76,7 +76,7 @@
//Document Inspector uses a different view from other files app activities.
final View view = activity.findViewById(R.id.fragment_container);
- Snackbar.make(view, R.string.file_inspector_load_error, Snackbar.LENGTH_INDEFINITE).show();
+ Snackbar.make(view, R.string.inspector_load_error, Snackbar.LENGTH_INDEFINITE).show();
}
public static final void showCustomTextWithImage(Activity activity, String text, int imageRes) {
diff --git a/tests/Android.mk b/tests/Android.mk
index cb1d64c..1dd259b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -12,13 +12,12 @@
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_AAPT_FLAGS += -0 .zip
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
LOCAL_STATIC_JAVA_LIBRARIES := \
mockito-target \
ub-uiautomator \
espresso-core \
- guava \
- legacy-android-test
+ guava
LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
LOCAL_PACKAGE_NAME := DocumentsUITests
LOCAL_COMPATIBILITY_SUITE := device-tests
diff --git a/tests/common/com/android/documentsui/PagingProvider.java b/tests/common/com/android/documentsui/PagingProvider.java
index ad5f32c..a113bd1 100644
--- a/tests/common/com/android/documentsui/PagingProvider.java
+++ b/tests/common/com/android/documentsui/PagingProvider.java
@@ -63,7 +63,7 @@
String parentDocumentId, String[] projection, Bundle queryArgs)
throws FileNotFoundException {
- // TODO: Content notification.
+ queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
MatrixCursor c = createDocCursor(projection);
Bundle extras = c.getExtras();
diff --git a/tests/common/com/android/documentsui/bots/InspectorBot.java b/tests/common/com/android/documentsui/bots/InspectorBot.java
index 55f9044..448a7b7 100644
--- a/tests/common/com/android/documentsui/bots/InspectorBot.java
+++ b/tests/common/com/android/documentsui/bots/InspectorBot.java
@@ -15,19 +15,24 @@
*/
package com.android.documentsui.bots;
-import android.annotation.StringRes;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
import android.app.Activity;
import android.content.Context;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiSelector;
+import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-
-import com.android.documentsui.inspector.DetailsView;
import com.android.documentsui.R;
+import com.android.documentsui.inspector.DetailsView;
+import com.android.documentsui.inspector.KeyValueRow;
+import com.android.documentsui.inspector.TableView;
+
+import java.util.HashMap;
+import java.util.Map;
public class InspectorBot extends Bots.BaseBot {
@@ -42,23 +47,45 @@
assertEquals(expected, text);
}
- public void assertRowPresent(@StringRes String key, String value, Activity activity)
+ public void assertRowPresent(String key, Activity activity)
throws Exception {
- assertTrue(isRowPresent(key, value, activity));
+ assertTrue(isRowPresent(key, activity));
}
- private boolean isRowPresent(@StringRes String key, String value, Activity activity)
+ public void assertRowEquals(String key, String value, Activity activity)
throws Exception {
- DetailsView detailsView = (DetailsView) activity.findViewById(R.id.inspector_details_view);
- int children = detailsView.getChildCount();
+ assertTrue(isRowEquals(key, value, activity));
+ }
+
+ private static Map<String, String> getTableRows(TableView table)
+ throws Exception {
+ Map<String, String> rows = new HashMap<>();
+ int children = table.getChildCount();
for (int i = 0; i < children; i++) {
- LinearLayout child = (LinearLayout) detailsView.getChildAt(i);
- TextView title = (TextView) child.getChildAt(0);
- if (title.getText().equals(key)) {
- TextView info = (TextView) child.getChildAt(1);
- return info.getText().equals(value);
+ View view = table.getChildAt(i);
+ if (view instanceof KeyValueRow) {
+ LinearLayout row = (LinearLayout) table.getChildAt(i);
+ TextView key = (TextView) row.getChildAt(0);
+ TextView value = (TextView) row.getChildAt(1);
+ rows.put(
+ String.valueOf(key.getText()),
+ String.valueOf(value.getText()));
}
}
- return false;
+ return rows;
+ }
+
+ private boolean isRowPresent(String key, Activity activity)
+ throws Exception {
+ DetailsView details = (DetailsView) activity.findViewById(R.id.inspector_details_view);
+ Map<String, String> rows = getTableRows(details);
+ return rows.containsKey(key);
+ }
+
+ private boolean isRowEquals(String key, String value, Activity activity)
+ throws Exception {
+ DetailsView details = (DetailsView) activity.findViewById(R.id.inspector_details_view);
+ Map<String, String> rows = getTableRows(details);
+ return rows.containsKey(key) && value.equals(rows.get(key));
}
}
diff --git a/tests/common/com/android/documentsui/dirlist/TestDocumentsAdapter.java b/tests/common/com/android/documentsui/dirlist/TestDocumentsAdapter.java
index c463bb2..e2160cf 100644
--- a/tests/common/com/android/documentsui/dirlist/TestDocumentsAdapter.java
+++ b/tests/common/com/android/documentsui/dirlist/TestDocumentsAdapter.java
@@ -16,10 +16,15 @@
package com.android.documentsui.dirlist;
+import static org.junit.Assert.assertTrue;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.AdapterDataObserver;
import android.view.ViewGroup;
-import com.android.documentsui.base.EventListener;
import com.android.documentsui.Model.Update;
+import com.android.documentsui.base.EventListener;
+import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.testing.TestEventListener;
import java.util.ArrayList;
@@ -30,11 +35,53 @@
*/
public class TestDocumentsAdapter extends DocumentsAdapter {
- List<String> mModelIds = new ArrayList<>();
final TestEventListener<Update> mModelListener = new TestEventListener<>();
+ List<String> mModelIds = new ArrayList<>();
+ private final AdapterDataObserver mAdapterObserver;
+ private final List<Integer> mSelectionChanged = new ArrayList<>();
public TestDocumentsAdapter(List<String> modelIds) {
mModelIds = modelIds;
+
+ mAdapterObserver = new RecyclerView.AdapterDataObserver() {
+
+ @Override
+ public void onChanged() {
+ }
+
+ @Override
+ public void onItemRangeChanged(int startPosition, int itemCount, Object payload) {
+ if (SelectionHelper.SELECTION_CHANGED_MARKER.equals(payload)) {
+ int last = startPosition + itemCount;
+ for (int i = startPosition; i < last; i++) {
+ mSelectionChanged.add(i);
+ }
+ }
+ }
+
+ @Override
+ public void onItemRangeInserted(int startPosition, int itemCount) {
+ }
+
+ @Override
+ public void onItemRangeRemoved(int startPosition, int itemCount) {
+ }
+
+ @Override
+ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ registerAdapterDataObserver(mAdapterObserver);
+ }
+
+ public void resetSelectionChanged() {
+ mSelectionChanged.clear();
+ }
+
+ public void assertSelectionChanged(int position) {
+ assertTrue(mSelectionChanged.contains(position));
}
@Override
@@ -43,16 +90,17 @@
}
@Override
- public List<String> getModelIds() {
+ public List<String> getStableIds() {
return mModelIds;
}
@Override
- public void onItemSelectionChanged(String id) {
+ public int getPosition(String id) {
+ return mModelIds.indexOf(id);
}
@Override
- public String getModelId(int position) {
+ public String getStableId(int position) {
return mModelIds.get(position);
}
diff --git a/tests/common/com/android/documentsui/dirlist/TestFocusHandler.java b/tests/common/com/android/documentsui/dirlist/TestFocusHandler.java
index 910a3c4..8dfbdea 100644
--- a/tests/common/com/android/documentsui/dirlist/TestFocusHandler.java
+++ b/tests/common/com/android/documentsui/dirlist/TestFocusHandler.java
@@ -16,6 +16,8 @@
package com.android.documentsui.dirlist;
+import static org.junit.Assert.assertEquals;
+
import android.view.KeyEvent;
import android.view.View;
@@ -80,4 +82,12 @@
focusModelId = null;
focusPos = 0;
}
-}
\ No newline at end of file
+
+ public void assertHasFocus(boolean focused) {
+ assertEquals(focused, hasFocusedItem());
+ }
+
+ public void assertFocused(String modelId) {
+ assertEquals(modelId, getFocusModelId());
+ }
+}
diff --git a/tests/common/com/android/documentsui/selection/TestItemSelectionListener.java b/tests/common/com/android/documentsui/selection/TestItemSelectionListener.java
deleted file mode 100644
index dfd8e2a..0000000
--- a/tests/common/com/android/documentsui/selection/TestItemSelectionListener.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class TestItemSelectionListener implements SelectionManager.ItemCallback {
-
- private final Set<String> mSelected = new HashSet<>();
-
- @Override
- public void onItemStateChanged(String id, boolean selected) {
- if (selected) {
- assertNotSelected(id);
- mSelected.add(id);
- } else {
- assertSelected(id);
- mSelected.remove(id);
- }
- }
-
- @Override
- public void onSelectionReset() {
- mSelected.clear();
- }
-
- void assertNoSelection() {
- assertTrue(mSelected.isEmpty());
- }
-
- void assertSelectionSize(int expected) {
- assertEquals(expected, mSelected.size());
- }
-
- void assertSelected(String id) {
- assertTrue(id + " is not selected.", mSelected.contains(id));
- }
-
- void assertNotSelected(String id) {
- assertFalse(id + " is already selected", mSelected.contains(id));
- }
-}
diff --git a/tests/common/com/android/documentsui/selection/TestSelectionListener.java b/tests/common/com/android/documentsui/selection/TestSelectionListener.java
deleted file mode 100644
index 62a86b0..0000000
--- a/tests/common/com/android/documentsui/selection/TestSelectionListener.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import com.android.documentsui.selection.SelectionManager;
-
-public final class TestSelectionListener implements SelectionManager.Callback {
-
- private boolean mSelectionChanged = false;
-
- @Override
- public void onSelectionChanged() {
- mSelectionChanged = true;
- }
-
- @Override
- public void onSelectionRestored() {}
-
- public void reset() {
- mSelectionChanged = false;
- }
-
- public void assertSelectionChanged() {
- assertTrue(mSelectionChanged);
- }
-
- public void assertSelectionUnchanged() {
- assertFalse(mSelectionChanged);
- }
-}
\ No newline at end of file
diff --git a/tests/common/com/android/documentsui/services/TestJob.java b/tests/common/com/android/documentsui/services/TestJob.java
index 3c4da22..10addeb 100644
--- a/tests/common/com/android/documentsui/services/TestJob.java
+++ b/tests/common/com/android/documentsui/services/TestJob.java
@@ -107,4 +107,8 @@
service.getString(android.R.string.cancel),
R.drawable.ic_cab_cancel);
}
+
+ @Override
+ void finish() {
+ }
}
diff --git a/tests/common/com/android/documentsui/testing/IntentAsserts.java b/tests/common/com/android/documentsui/testing/IntentAsserts.java
index 6fc1ae0..cbd6f38 100644
--- a/tests/common/com/android/documentsui/testing/IntentAsserts.java
+++ b/tests/common/com/android/documentsui/testing/IntentAsserts.java
@@ -40,6 +40,14 @@
assertEquals(expected, intent.getAction());
}
+ public static void assertTargetsComponent(Intent intent, Class<?> expected) {
+ assertEquals(expected.getName(), intent.getComponent().getClassName());
+ }
+
+ public static void assertHasExtra(Intent intent, String key) {
+ assertTrue(intent.getExtras().containsKey(key));
+ }
+
public static Intent assertHasExtraIntent(Intent intent) {
Intent extra = (Intent) intent.getExtra(EXTRA_INTENT);
assertNotNull(extra);
@@ -64,4 +72,8 @@
Assert.assertEquals(size, list.size());
return list;
}
+
+ public static void assertHasData(Intent intent, Uri expected) {
+ assertEquals(expected, intent.getData());
+ }
}
diff --git a/tests/common/com/android/documentsui/testing/SelectionHelpers.java b/tests/common/com/android/documentsui/testing/SelectionHelpers.java
new file mode 100644
index 0000000..70bc44d
--- /dev/null
+++ b/tests/common/com/android/documentsui/testing/SelectionHelpers.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.testing;
+
+import com.android.documentsui.DocsSelectionHelper;
+import com.android.documentsui.dirlist.DocsStableIdProvider;
+import com.android.documentsui.dirlist.DocumentsAdapter;
+import com.android.documentsui.dirlist.TestDocumentsAdapter;
+import com.android.documentsui.selection.DefaultSelectionHelper;
+import com.android.documentsui.selection.DefaultSelectionHelper.SelectionMode;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SelectionHelpers {
+
+ public static final SelectionPredicate CAN_SET_ANYTHING = new SelectionPredicate() {
+ @Override
+ public boolean canSetStateForId(String id, boolean nextState) {
+ return true;
+ }
+
+ @Override
+ public boolean canSetStateAtPosition(int position, boolean nextState) {
+ return true;
+ }
+ };
+
+ private SelectionHelpers() {}
+
+ public static DocsSelectionHelper createTestInstance() {
+ return createTestInstance(Collections.emptyList());
+ }
+
+ public static DocsSelectionHelper createTestInstance(List<String> docs) {
+ return createTestInstance(docs, DefaultSelectionHelper.MODE_MULTIPLE);
+ }
+
+ public static DocsSelectionHelper createTestInstance(
+ List<String> docs, @SelectionMode int mode) {
+ return createTestInstance(new TestDocumentsAdapter(docs), mode, CAN_SET_ANYTHING);
+ }
+
+ public static DocsSelectionHelper createTestInstance(
+ DocumentsAdapter adapter, @SelectionMode int mode, SelectionPredicate canSetState) {
+ DocsSelectionHelper manager = mode == DefaultSelectionHelper.MODE_SINGLE
+ ? DocsSelectionHelper.createSingleSelect()
+ : DocsSelectionHelper.createMultiSelect();
+
+ manager.reset(adapter, new DocsStableIdProvider(adapter), canSetState);
+
+ return manager;
+ }
+}
diff --git a/tests/common/com/android/documentsui/testing/SelectionManagers.java b/tests/common/com/android/documentsui/testing/SelectionManagers.java
deleted file mode 100644
index c4f29a0..0000000
--- a/tests/common/com/android/documentsui/testing/SelectionManagers.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.testing;
-
-import com.android.documentsui.dirlist.DocumentsAdapter;
-import com.android.documentsui.dirlist.TestDocumentsAdapter;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.selection.SelectionManager.SelectionMode;
-import com.android.documentsui.selection.SelectionManager.SelectionPredicate;
-
-import java.util.Collections;
-import java.util.List;
-
-public class SelectionManagers {
- private SelectionManagers() {}
-
- public static SelectionManager createTestInstance() {
- return createTestInstance(Collections.emptyList());
- }
-
- public static SelectionManager createTestInstance(List<String> docs) {
- return createTestInstance(docs, SelectionManager.MODE_MULTIPLE);
- }
-
- public static SelectionManager createTestInstance(
- List<String> docs, @SelectionMode int mode) {
- return createTestInstance(
- new TestDocumentsAdapter(docs),
- mode,
- (String id, boolean nextState) -> true);
- }
-
- public static SelectionManager createTestInstance(
- DocumentsAdapter adapter, @SelectionMode int mode, SelectionPredicate canSetState) {
- SelectionManager manager = new SelectionManager(mode);
- manager.reset(adapter, canSetState);
-
- return manager;
- }
-}
diff --git a/tests/common/com/android/documentsui/testing/TestActionHandler.java b/tests/common/com/android/documentsui/testing/TestActionHandler.java
index 8353569..cd3fb1a 100644
--- a/tests/common/com/android/documentsui/testing/TestActionHandler.java
+++ b/tests/common/com/android/documentsui/testing/TestActionHandler.java
@@ -22,7 +22,7 @@
import com.android.documentsui.TestActivity;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.RootInfo;
-import com.android.documentsui.dirlist.DocumentDetails;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
import java.util.function.Consumer;
@@ -30,7 +30,7 @@
private final TestEnv mEnv;
- public final TestEventHandler<DocumentDetails> open = new TestEventHandler<>();
+ public final TestEventHandler<ItemDetails> open = new TestEventHandler<>();
public boolean mDeleteHappened;
public DocumentInfo nextRootDocument;
@@ -53,7 +53,7 @@
}
@Override
- public boolean openDocument(DocumentDetails doc, @ViewType int type, @ViewType int fallback) {
+ public boolean openItem(ItemDetails doc, @ViewType int type, @ViewType int fallback) {
return open.accept(doc);
}
diff --git a/tests/common/com/android/documentsui/testing/TestEnv.java b/tests/common/com/android/documentsui/testing/TestEnv.java
index 96ee0b7..40b5e0a 100644
--- a/tests/common/com/android/documentsui/testing/TestEnv.java
+++ b/tests/common/com/android/documentsui/testing/TestEnv.java
@@ -15,10 +15,12 @@
*/
package com.android.documentsui.testing;
+import android.content.Context;
import android.provider.DocumentsContract.Document;
import android.support.test.InstrumentationRegistry;
import android.test.mock.MockContentResolver;
+import com.android.documentsui.DocsSelectionHelper;
import com.android.documentsui.FocusManager;
import com.android.documentsui.Injector;
import com.android.documentsui.archives.ArchivesProvider;
@@ -27,12 +29,9 @@
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.TestFocusHandler;
-import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.sorting.SortModel;
import com.android.documentsui.ui.TestDialogController;
-import junit.framework.Assert;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -49,6 +48,7 @@
public static DocumentInfo FILE_JPG;
public static DocumentInfo FILE_GIF;
public static DocumentInfo FILE_PDF;
+ public static DocumentInfo FILE_MP4;
public static DocumentInfo FILE_APK;
public static DocumentInfo FILE_PARTIAL;
public static DocumentInfo FILE_ARCHIVE;
@@ -64,29 +64,27 @@
public final TestDialogController dialogs = new TestDialogController();
public final TestModel model;
public final TestModel archiveModel;
- public final SelectionManager selectionMgr;
+ public final DocsSelectionHelper selectionMgr;
public final TestSearchViewManager searchViewManager;
- public final Injector injector;
+ public final Injector<?> injector;
public final Features features;
public final MockContentResolver contentResolver;
public final Map<String, TestDocumentsProvider> mockProviders;
- private TestEnv(String authority) {
+ private TestEnv(Context context, Features features, String authority) {
+ this.features = features;
state.sortModel = SortModel.createModel();
mExecutor = new TestScheduledExecutorService();
- features = new Features.RuntimeFeatures(
- InstrumentationRegistry.getInstrumentation().getTargetContext().getResources(),
- null);
model = new TestModel(authority, features);
archiveModel = new TestModel(ArchivesProvider.AUTHORITY, features);
- selectionMgr = SelectionManagers.createTestInstance();
+ selectionMgr = SelectionHelpers.createTestInstance();
searchViewManager = new TestSearchViewManager();
injector = new Injector(
features,
new TestActivityConfig(),
- null, //ScopedPreferences are not required for tests
- null, //a MessageBuilder is not required for tests
+ null, // ScopedPreferences are not currently required for tests
+ null, // MessageBuilder is not currently required for tests
dialogs,
new TestFileTypeLookup(),
(roots) -> {}, // not sure why, but java gets angry when I declare roots type.
@@ -111,12 +109,28 @@
}
}
+ // Many terrible creational permutations == easy to user for test authors!
+ public static TestEnv create(Features features) {
+ return create(features, TestProvidersAccess.HOME.authority);
+ }
+
public static TestEnv create() {
return create(TestProvidersAccess.HOME.authority);
}
+ public static TestEnv create(Features features, String authority) {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ return create(context, features, authority);
+ }
+
public static TestEnv create(String authority) {
- TestEnv env = new TestEnv(authority);
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ Features features = new Features.RuntimeFeatures(context.getResources(), null);
+ return create(context, features, authority);
+ }
+
+ private static TestEnv create(Context context, Features features, String authority) {
+ TestEnv env = new TestEnv(context, features, authority);
env.reset();
return env;
}
@@ -136,6 +150,7 @@
FILE_JPG = model.createFile("jiffy.jpg");
FILE_GIF = model.createFile("glibby.gif");
FILE_PDF = model.createFile("busy.pdf");
+ FILE_MP4 = model.createFile("cameravideo.mp4");
FILE_APK = model.createFile("becareful.apk");
FILE_PARTIAL = model.createFile(
"UbuntuFlappyBird.iso",
@@ -157,8 +172,11 @@
public void populateStack() {
DocumentInfo rootDoc = model.getDocument("1");
- Assert.assertNotNull(rootDoc);
- Assert.assertEquals(rootDoc.displayName, FOLDER_0.displayName);
+
+ // These are test setup sanity checks, not test assertions.
+ assert rootDoc != null;
+ assert rootDoc.isDirectory();
+ assert FOLDER_0.equals(rootDoc);
state.stack.changeRoot(TestProvidersAccess.HOME);
state.stack.push(rootDoc);
@@ -177,4 +195,21 @@
ids.add(info.documentId);
selectionMgr.setItemsSelected(ids, true);
}
+
+ // Easily copy docs, so we don't pollute static data across tests.
+ public static DocumentInfo clone(DocumentInfo a) {
+ DocumentInfo b = new DocumentInfo();
+ b.authority = a.authority;
+ b.documentId = a.documentId;
+ b.mimeType = a.mimeType;
+ b.displayName = a.displayName;
+ b.lastModified = a.lastModified;
+ b.flags = a.flags;
+ b.summary = a.summary;
+ b.size = a.size;
+ b.icon = a.icon;
+ b.derivedUri = a.derivedUri;
+
+ return b;
+ }
}
diff --git a/tests/common/com/android/documentsui/testing/TestEvent.java b/tests/common/com/android/documentsui/testing/TestEvent.java
deleted file mode 100644
index bc77211..0000000
--- a/tests/common/com/android/documentsui/testing/TestEvent.java
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.testing;
-
-import android.annotation.IntDef;
-import android.graphics.Point;
-import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.dirlist.DocumentDetails;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Events and DocDetails are closely related. For the pursposes of this test
- * we coalesce the two in a single, handy-dandy test class.
- */
-public class TestEvent implements InputEvent {
- private static final int ACTION_UNSET = -1;
-
- // Add other actions from MotionEvent.ACTION_ as needed.
- @IntDef(flag = true, value = {
- MotionEvent.ACTION_DOWN,
- MotionEvent.ACTION_MOVE,
- MotionEvent.ACTION_UP
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Action {}
-
- // Add other types from MotionEvent.TOOL_TYPE_ as needed.
- @IntDef(flag = true, value = {
- MotionEvent.TOOL_TYPE_FINGER,
- MotionEvent.TOOL_TYPE_MOUSE,
- MotionEvent.TOOL_TYPE_STYLUS,
- MotionEvent.TOOL_TYPE_UNKNOWN
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ToolType {}
-
- @IntDef(flag = true, value = {
- MotionEvent.BUTTON_PRIMARY,
- MotionEvent.BUTTON_SECONDARY
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Button {}
-
- @IntDef(flag = true, value = {
- KeyEvent.META_SHIFT_ON,
- KeyEvent.META_CTRL_ON
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Key {}
-
- private @Action int mAction;
- private @ToolType int mToolType;
- private int mPointerCount;
- private Set<Integer> mButtons;
- private Set<Integer> mKeys;
- private Point mLocation;
- private Point mRawLocation;
- private Details mDetails;
-
- private TestEvent() {
- mAction = ACTION_UNSET; // somebody has to set this, else we'll barf later.
- mToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
- mButtons = new HashSet<>();
- mKeys = new HashSet<>();
- mLocation = new Point(0, 0);
- mRawLocation = new Point(0, 0);
- mDetails = new Details();
- mPointerCount = 0;
- }
-
- private TestEvent(TestEvent source) {
- assert(source.mAction != ACTION_UNSET);
- mAction = source.mAction;
- mToolType = source.mToolType;
- mButtons = source.mButtons;
- mKeys = source.mKeys;
- mLocation = source.mLocation;
- mRawLocation = source.mRawLocation;
- mDetails = new Details(source.mDetails);
- mPointerCount = source.mPointerCount;
- }
-
- @Override
- public Point getOrigin() {
- return mLocation;
- }
-
- @Override
- public float getX() {
- return mLocation.x;
- }
-
- @Override
- public float getY() {
- return mLocation.y;
- }
-
- @Override
- public float getRawX() {
- return mRawLocation.x;
- }
-
- @Override
- public float getRawY() {
- return mRawLocation.y;
- }
-
- @Override
- public int getPointerCount() {
- return mPointerCount;
- }
-
- @Override
- public boolean isMouseEvent() {
- return mToolType == MotionEvent.TOOL_TYPE_MOUSE;
- }
-
- @Override
- public boolean isPrimaryButtonPressed() {
- return mButtons.contains(MotionEvent.BUTTON_PRIMARY);
- }
-
- @Override
- public boolean isSecondaryButtonPressed() {
- return mButtons.contains(MotionEvent.BUTTON_SECONDARY);
- }
-
- @Override
- public boolean isTertiaryButtonPressed() {
- return mButtons.contains(MotionEvent.BUTTON_TERTIARY);
- }
-
- @Override
- public boolean isShiftKeyDown() {
- return mKeys.contains(KeyEvent.META_SHIFT_ON);
- }
-
- @Override
- public boolean isCtrlKeyDown() {
- return mKeys.contains(KeyEvent.META_CTRL_ON);
- }
-
- @Override
- public boolean isAltKeyDown() {
- return mKeys.contains(KeyEvent.META_ALT_ON);
- }
-
- @Override
- public boolean isActionDown() {
- return mAction == MotionEvent.ACTION_DOWN;
- }
-
- @Override
- public boolean isActionUp() {
- return mAction == MotionEvent.ACTION_UP;
- }
-
- @Override
- public boolean isMultiPointerActionDown() {
- return mAction == MotionEvent.ACTION_POINTER_DOWN;
- }
-
- @Override
- public boolean isMultiPointerActionUp() {
- return mAction == MotionEvent.ACTION_POINTER_UP;
- }
-
- @Override
- public boolean isActionMove() {
- return mAction == MotionEvent.ACTION_MOVE;
- }
-
- @Override
- public boolean isActionCancel() {
- return mAction == MotionEvent.ACTION_CANCEL;
- }
-
- @Override
- public boolean isOverItem() {
- return mDetails.isOverItem();
- }
-
- @Override
- public boolean isOverDocIcon() {
- return mDetails.isOverDocIcon(this);
- }
-
- @Override
- public boolean isOverDragHotspot() {
- return isOverItem() && mDetails.isInDragHotspot(this);
- }
-
- @Override
- public boolean isOverModelItem() {
- if (isOverItem()) {
- DocumentDetails doc = getDocumentDetails();
- return doc != null && doc.hasModelId();
- }
- return false;
- }
-
- @Override
- public boolean isTouchpadScroll() {
- return isMouseEvent() && mButtons.isEmpty() && isActionMove();
- }
-
- @Override
- public int getItemPosition() {
- return mDetails.mPosition;
- }
-
- @Override
- public DocumentDetails getDocumentDetails() {
- return mDetails;
- }
-
- @Override
- public void close() {}
-
- @Override
- public int hashCode() {
- return mDetails.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof TestEvent)) {
- return false;
- }
-
- TestEvent other = (TestEvent) o;
- return mAction == other.mAction
- && mToolType == other.mToolType
- && mButtons.equals(other.mButtons)
- && mKeys.equals(other.mKeys)
- && mLocation.equals(other.mLocation)
- && mRawLocation.equals(other.mRawLocation)
- && mDetails.equals(other.mDetails);
- }
-
- private static final class Details implements DocumentDetails {
-
- private int mPosition;
- private String mModelId;
- private boolean mInSelectionHotspot;
- private boolean mInDragHotspot;
- private boolean mOverDocIcon;
-
- public Details() {
- mPosition = Integer.MIN_VALUE;
- }
-
- public Details(Details source) {
- mPosition = source.mPosition;
- mModelId = source.mModelId;
- mInSelectionHotspot = source.mInSelectionHotspot;
- mInDragHotspot = source.mInDragHotspot;
- mOverDocIcon = source.mOverDocIcon;
- }
-
-
- private boolean isOverItem() {
- return mPosition != Integer.MIN_VALUE && mPosition != RecyclerView.NO_POSITION;
- }
-
- @Override
- public boolean hasModelId() {
- return !TextUtils.isEmpty(mModelId);
- }
-
- @Override
- public String getModelId() {
- return mModelId;
- }
-
- @Override
- public int getAdapterPosition() {
- return mPosition;
- }
-
- @Override
- public boolean isInSelectionHotspot(InputEvent event) {
- return mInSelectionHotspot;
- }
-
- @Override
- public boolean isInDragHotspot(InputEvent event) {
- return mInDragHotspot;
- }
-
- @Override
- public boolean isOverDocIcon(InputEvent event) {
- return mOverDocIcon;
- }
-
- @Override
- public int hashCode() {
- return mModelId != null ? mModelId.hashCode() : ACTION_UNSET;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof Details)) {
- return false;
- }
-
- Details other = (Details) o;
- return mPosition == other.mPosition
- && mModelId == other.mModelId;
- }
- }
-
- public static final Builder builder() {
- return new Builder();
- }
-
- /**
- * Test event builder with convenience methods for common event attrs.
- */
- public static final class Builder {
-
- private TestEvent mState = new TestEvent();
-
- public Builder() {
- }
-
- public Builder(TestEvent state) {
- mState = new TestEvent(state);
- }
-
- /**
- * @param action Any action specified in {@link MotionEvent}.
- * @return
- */
- public Builder action(int action) {
- mState.mAction = action;
- return this;
- }
-
- public Builder type(@ToolType int type) {
- mState.mToolType = type;
- return this;
- }
-
- public Builder location(int x, int y) {
- mState.mLocation = new Point(x, y);
- return this;
- }
-
- public Builder rawLocation(int x, int y) {
- mState.mRawLocation = new Point(x, y);
- return this;
- }
-
- public Builder pointerCount(int count) {
- mState.mPointerCount = count;
- return this;
- }
-
- /**
- * Adds one or more button press attributes.
- */
- public Builder pressButton(@Button int... buttons) {
- for (int button : buttons) {
- mState.mButtons.add(button);
- }
- return this;
- }
-
- /**
- * Removes one or more button press attributes.
- */
- public Builder releaseButton(@Button int... buttons) {
- for (int button : buttons) {
- mState.mButtons.remove(button);
- }
- return this;
- }
-
- /**
- * Adds one or more key press attributes.
- */
- public Builder pressKey(@Key int... keys) {
- for (int key : keys) {
- mState.mKeys.add(key);
- }
- return this;
- }
-
- /**
- * Removes one or more key press attributes.
- */
- public Builder releaseKey(@Button int... keys) {
- for (int key : keys) {
- mState.mKeys.remove(key);
- }
- return this;
- }
-
- public Builder at(int position) {
- mState.mDetails.mPosition = position; // this is both "adapter position" and "item position".
- mState.mDetails.mModelId = String.valueOf(position);
- return this;
- }
-
- public Builder inSelectionHotspot() {
- mState.mDetails.mInSelectionHotspot = true;
- return this;
- }
-
- public Builder inDragHotspot() {
- mState.mDetails.mInDragHotspot = true;
- return this;
- }
-
- public Builder notInDragHotspot() {
- mState.mDetails.mInDragHotspot = false;
- return this;
- }
-
- public Builder overDocIcon() {
- mState.mDetails.mOverDocIcon = true;
- return this;
- }
-
- public Builder notOverDocIcon() {
- mState.mDetails.mOverDocIcon = false;
- return this;
- }
-
- public Builder touch() {
- type(MotionEvent.TOOL_TYPE_FINGER);
- return this;
- }
-
- public Builder mouse() {
- type(MotionEvent.TOOL_TYPE_MOUSE);
- return this;
- }
-
- public Builder shift() {
- pressKey(KeyEvent.META_SHIFT_ON);
- return this;
- }
-
- /**
- * Use {@link #remove(@Attribute int...)}
- */
- @Deprecated
- public Builder unshift() {
- releaseKey(KeyEvent.META_SHIFT_ON);
- return this;
- }
-
- public Builder ctrl() {
- pressKey(KeyEvent.META_CTRL_ON);
- return this;
- }
-
- public Builder alt() {
- pressKey(KeyEvent.META_ALT_ON);
- return this;
- }
-
- public Builder primary() {
- pressButton(MotionEvent.BUTTON_PRIMARY);
- releaseButton(MotionEvent.BUTTON_SECONDARY);
- releaseButton(MotionEvent.BUTTON_TERTIARY);
- return this;
- }
-
- public Builder secondary() {
- pressButton(MotionEvent.BUTTON_SECONDARY);
- releaseButton(MotionEvent.BUTTON_PRIMARY);
- releaseButton(MotionEvent.BUTTON_TERTIARY);
- return this;
- }
-
- public Builder tertiary() {
- pressButton(MotionEvent.BUTTON_TERTIARY);
- releaseButton(MotionEvent.BUTTON_PRIMARY);
- releaseButton(MotionEvent.BUTTON_SECONDARY);
- return this;
- }
-
- public Builder reset() {
- mState = new TestEvent();
- return this;
- }
-
- @Override
- public Builder clone() {
- return new Builder(build());
- }
-
- public TestEvent build() {
- // Return a copy, so nobody can mess w/ our internal state.
- return new TestEvent(mState);
- }
- }
-}
diff --git a/tests/common/com/android/documentsui/testing/TestEvents.java b/tests/common/com/android/documentsui/testing/TestEvents.java
new file mode 100644
index 0000000..9aab9e8
--- /dev/null
+++ b/tests/common/com/android/documentsui/testing/TestEvents.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.testing;
+
+import android.annotation.IntDef;
+import android.graphics.Point;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Handy-dandy wrapper class to facilitate the creation of MotionEvents.
+ */
+public final class TestEvents {
+
+ /**
+ * Common mouse event types...for your convenience.
+ */
+ public static final class Mouse {
+ public static final MotionEvent CLICK =
+ TestEvents.builder().mouse().primary().build();
+ public static final MotionEvent CTRL_CLICK =
+ TestEvents.builder().mouse().primary().ctrl().build();
+ public static final MotionEvent ALT_CLICK =
+ TestEvents.builder().mouse().primary().alt().build();
+ public static final MotionEvent SHIFT_CLICK =
+ TestEvents.builder().mouse().primary().shift().build();
+ public static final MotionEvent SECONDARY_CLICK =
+ TestEvents.builder().mouse().secondary().build();
+ public static final MotionEvent TERTIARY_CLICK =
+ TestEvents.builder().mouse().tertiary().build();
+ }
+
+ /**
+ * Common touch event types...for your convenience.
+ */
+ public static final class Touch {
+ public static final MotionEvent TAP =
+ TestEvents.builder().touch().build();
+ }
+
+ static final int ACTION_UNSET = -1;
+
+ // Add other actions from MotionEvent.ACTION_ as needed.
+ @IntDef(flag = true, value = {
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_MOVE,
+ MotionEvent.ACTION_UP
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Action {}
+
+ // Add other types from MotionEvent.TOOL_TYPE_ as needed.
+ @IntDef(flag = true, value = {
+ MotionEvent.TOOL_TYPE_FINGER,
+ MotionEvent.TOOL_TYPE_MOUSE,
+ MotionEvent.TOOL_TYPE_STYLUS,
+ MotionEvent.TOOL_TYPE_UNKNOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ToolType {}
+
+ @IntDef(flag = true, value = {
+ MotionEvent.BUTTON_PRIMARY,
+ MotionEvent.BUTTON_SECONDARY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Button {}
+
+ @IntDef(flag = true, value = {
+ KeyEvent.META_SHIFT_ON,
+ KeyEvent.META_CTRL_ON
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Key {}
+
+ private static final class State {
+ private @Action int mAction = ACTION_UNSET;
+ private @ToolType int mToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
+ private int mPointerCount = 1;
+ private Set<Integer> mButtons = new HashSet<>();
+ private Set<Integer> mKeys = new HashSet<>();
+ private Point mLocation = new Point(0, 0);
+ private Point mRawLocation = new Point(0, 0);
+ }
+
+ public static final Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Test event builder with convenience methods for common event attrs.
+ */
+ public static final class Builder {
+
+ private State mState = new State();
+
+ /**
+ * @param action Any action specified in {@link MotionEvent}.
+ * @return
+ */
+ public Builder action(int action) {
+ mState.mAction = action;
+ return this;
+ }
+
+ public Builder type(@ToolType int type) {
+ mState.mToolType = type;
+ return this;
+ }
+
+ public Builder location(int x, int y) {
+ mState.mLocation = new Point(x, y);
+ return this;
+ }
+
+ public Builder rawLocation(int x, int y) {
+ mState.mRawLocation = new Point(x, y);
+ return this;
+ }
+
+ public Builder pointerCount(int count) {
+ mState.mPointerCount = count;
+ return this;
+ }
+
+ /**
+ * Adds one or more button press attributes.
+ */
+ public Builder pressButton(@Button int... buttons) {
+ for (int button : buttons) {
+ mState.mButtons.add(button);
+ }
+ return this;
+ }
+
+ /**
+ * Removes one or more button press attributes.
+ */
+ public Builder releaseButton(@Button int... buttons) {
+ for (int button : buttons) {
+ mState.mButtons.remove(button);
+ }
+ return this;
+ }
+
+ /**
+ * Adds one or more key press attributes.
+ */
+ public Builder pressKey(@Key int... keys) {
+ for (int key : keys) {
+ mState.mKeys.add(key);
+ }
+ return this;
+ }
+
+ /**
+ * Removes one or more key press attributes.
+ */
+ public Builder releaseKey(@Button int... keys) {
+ for (int key : keys) {
+ mState.mKeys.remove(key);
+ }
+ return this;
+ }
+
+ public Builder touch() {
+ type(MotionEvent.TOOL_TYPE_FINGER);
+ return this;
+ }
+
+ public Builder mouse() {
+ type(MotionEvent.TOOL_TYPE_MOUSE);
+ return this;
+ }
+
+ public Builder shift() {
+ pressKey(KeyEvent.META_SHIFT_ON);
+ return this;
+ }
+
+ /**
+ * Use {@link #remove(@Attribute int...)}
+ */
+ public Builder unshift() {
+ releaseKey(KeyEvent.META_SHIFT_ON);
+ return this;
+ }
+
+ public Builder ctrl() {
+ pressKey(KeyEvent.META_CTRL_ON);
+ return this;
+ }
+
+ public Builder alt() {
+ pressKey(KeyEvent.META_ALT_ON);
+ return this;
+ }
+
+ public Builder primary() {
+ pressButton(MotionEvent.BUTTON_PRIMARY);
+ releaseButton(MotionEvent.BUTTON_SECONDARY);
+ releaseButton(MotionEvent.BUTTON_TERTIARY);
+ return this;
+ }
+
+ public Builder secondary() {
+ pressButton(MotionEvent.BUTTON_SECONDARY);
+ releaseButton(MotionEvent.BUTTON_PRIMARY);
+ releaseButton(MotionEvent.BUTTON_TERTIARY);
+ return this;
+ }
+
+ public Builder tertiary() {
+ pressButton(MotionEvent.BUTTON_TERTIARY);
+ releaseButton(MotionEvent.BUTTON_PRIMARY);
+ releaseButton(MotionEvent.BUTTON_SECONDARY);
+ return this;
+ }
+
+ public MotionEvent build() {
+
+ PointerProperties[] pointers = new PointerProperties[1];
+ pointers[0] = new PointerProperties();
+ pointers[0].id = 0;
+ pointers[0].toolType = mState.mToolType;
+
+ PointerCoords[] coords = new PointerCoords[1];
+ coords[0] = new PointerCoords();
+ coords[0].x = mState.mLocation.x;
+ coords[0].y = mState.mLocation.y;
+
+ int buttons = 0;
+ for (Integer button : mState.mButtons) {
+ buttons |= button;
+ }
+
+ int keys = 0;
+ for (Integer key : mState.mKeys) {
+ keys |= key;
+ }
+
+ return MotionEvent.obtain(
+ 0, // down time
+ 1, // event time
+ mState.mAction,
+ 1, // pointerCount,
+ pointers,
+ coords,
+ keys,
+ buttons,
+ 1.0f, // x precision
+ 1.0f, // y precision
+ 0, // device id
+ 0, // edge flags
+ 0, // int source,
+ 0 // int flags
+ );
+ }
+ }
+}
diff --git a/tests/common/com/android/documentsui/testing/TestGridLayoutManager.java b/tests/common/com/android/documentsui/testing/TestGridLayoutManager.java
new file mode 100644
index 0000000..f883e5e
--- /dev/null
+++ b/tests/common/com/android/documentsui/testing/TestGridLayoutManager.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.testing;
+
+import android.content.Context;
+import android.support.v7.widget.GridLayoutManager;
+
+import org.mockito.Mockito;
+
+public class TestGridLayoutManager extends GridLayoutManager {
+
+ private int mFirstVisibleItemPosition;
+
+ public static TestGridLayoutManager create() {
+ final TestGridLayoutManager manager = Mockito.mock(TestGridLayoutManager.class,
+ Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
+ return manager;
+ }
+
+ @Override
+ public int findFirstVisibleItemPosition() { return mFirstVisibleItemPosition; }
+
+ public void setFirstVisibleItemPosition(int position) { mFirstVisibleItemPosition = position; }
+
+ private TestGridLayoutManager(Context context, int spanCount) {
+ super(context, spanCount);
+ }
+}
diff --git a/tests/common/com/android/documentsui/testing/TestMenu.java b/tests/common/com/android/documentsui/testing/TestMenu.java
index 9df06d9..6a46668 100644
--- a/tests/common/com/android/documentsui/testing/TestMenu.java
+++ b/tests/common/com/android/documentsui/testing/TestMenu.java
@@ -18,6 +18,7 @@
import android.util.SparseArray;
import android.view.Menu;
+import android.widget.SearchView;
import com.android.documentsui.R;
@@ -48,8 +49,9 @@
R.id.dir_menu_rename,
R.id.dir_menu_delete,
R.id.dir_menu_view_in_owner,
- R.id.dir_menu_open_in_new_window,
R.id.dir_menu_paste_into_folder,
+ R.id.dir_menu_inspect,
+ R.id.dir_menu_open_in_new_window,
R.id.root_menu_eject_root,
R.id.root_menu_open_in_new_window,
R.id.root_menu_paste_into_folder,
@@ -64,7 +66,7 @@
R.id.action_menu_move_to,
R.id.action_menu_compress,
R.id.action_menu_rename,
- R.id.action_menu_inspector,
+ R.id.action_menu_inspect,
R.id.action_menu_view_in_owner,
R.id.option_menu_search,
R.id.option_menu_debug,
@@ -74,7 +76,8 @@
R.id.option_menu_create_dir,
R.id.option_menu_select_all,
R.id.option_menu_advanced,
- R.id.option_menu_settings);
+ R.id.option_menu_settings,
+ R.id.option_menu_inspect);
}
@@ -86,6 +89,11 @@
for (int id : ids) {
TestMenuItem item = TestMenuItem.create(id);
menu.addMenuItem(id, item);
+
+ // Used by SearchViewManager
+ if (id == R.id.option_menu_search) {
+ item.setActionView(Mockito.mock(SearchView.class));
+ }
}
return menu;
}
diff --git a/tests/common/com/android/documentsui/testing/TestMenuItem.java b/tests/common/com/android/documentsui/testing/TestMenuItem.java
index a955adc..9f4df28 100644
--- a/tests/common/com/android/documentsui/testing/TestMenuItem.java
+++ b/tests/common/com/android/documentsui/testing/TestMenuItem.java
@@ -21,6 +21,7 @@
import android.annotation.StringRes;
import android.view.MenuItem;
+import android.view.View;
import org.mockito.Mockito;
@@ -37,6 +38,7 @@
boolean enabled;
boolean visible;
+ View actionView;
@StringRes int title;
public static TestMenuItem create(int id) {
@@ -83,6 +85,17 @@
return this.enabled;
}
+ @Override
+ final public MenuItem setActionView(View actionView) {
+ this.actionView = actionView;
+ return this;
+ }
+
+ @Override
+ final public View getActionView() {
+ return this.actionView;
+ }
+
public void assertEnabled() {
assertTrue(this.enabled);
}
diff --git a/tests/common/com/android/documentsui/testing/TestModel.java b/tests/common/com/android/documentsui/testing/TestModel.java
index 517b1f4..0df9b3a 100644
--- a/tests/common/com/android/documentsui/testing/TestModel.java
+++ b/tests/common/com/android/documentsui/testing/TestModel.java
@@ -53,6 +53,7 @@
reset();
}
+ @Override
public void reset() {
mLastId = 0;
mCursor = new MatrixCursor(COLUMNS);
diff --git a/tests/common/com/android/documentsui/testing/TestProvidersAccess.java b/tests/common/com/android/documentsui/testing/TestProvidersAccess.java
index abe95d1..248bb53 100644
--- a/tests/common/com/android/documentsui/testing/TestProvidersAccess.java
+++ b/tests/common/com/android/documentsui/testing/TestProvidersAccess.java
@@ -16,6 +16,7 @@
package com.android.documentsui.testing;
import android.provider.DocumentsContract.Root;
+
import com.android.documentsui.InspectorProvider;
import com.android.documentsui.base.Providers;
import com.android.documentsui.base.RootInfo;
@@ -45,6 +46,7 @@
}};
DOWNLOADS.authority = Providers.AUTHORITY_DOWNLOADS;
DOWNLOADS.rootId = Providers.ROOT_ID_DOWNLOADS;
+ DOWNLOADS.title = "Downloads";
DOWNLOADS.flags = Root.FLAG_LOCAL_ONLY
| Root.FLAG_SUPPORTS_CREATE
| Root.FLAG_SUPPORTS_IS_CHILD
@@ -53,6 +55,7 @@
HOME = new RootInfo();
HOME.authority = Providers.AUTHORITY_STORAGE;
HOME.rootId = Providers.ROOT_ID_HOME;
+ HOME.title = "Home";
HOME.flags = Root.FLAG_LOCAL_ONLY
| Root.FLAG_SUPPORTS_CREATE
| Root.FLAG_SUPPORTS_IS_CHILD
@@ -61,10 +64,12 @@
HAMMY = new RootInfo();
HAMMY.authority = "yummies";
HAMMY.rootId = "hamsandwich";
+ HAMMY.title = "Ham Sandwich";
PICKLES = new RootInfo();
PICKLES.authority = "yummies";
PICKLES.rootId = "pickles";
+ PICKLES.title = "Pickles";
RECENTS = new RootInfo() {{
// Special root for recents
@@ -72,10 +77,12 @@
flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD;
availableBytes = -1;
}};
+ RECENTS.title = "Recents";
INSPECTOR = new RootInfo();
INSPECTOR.authority = InspectorProvider.AUTHORITY;
INSPECTOR.rootId = InspectorProvider.ROOT_ID;
+ INSPECTOR.title = "Inspector";
INSPECTOR.flags = Root.FLAG_LOCAL_ONLY
| Root.FLAG_SUPPORTS_CREATE;
}
diff --git a/tests/common/com/android/documentsui/testing/TestRecyclerView.java b/tests/common/com/android/documentsui/testing/TestRecyclerView.java
index 8759a9a..a1f8e7f 100644
--- a/tests/common/com/android/documentsui/testing/TestRecyclerView.java
+++ b/tests/common/com/android/documentsui/testing/TestRecyclerView.java
@@ -17,6 +17,7 @@
package com.android.documentsui.testing;
import android.content.Context;
+import android.support.test.InstrumentationRegistry;
import android.support.v7.widget.RecyclerView;
import android.view.View;
@@ -32,6 +33,7 @@
private List<RecyclerView.ViewHolder> holders = new ArrayList<>();
private TestDocumentsAdapter adapter;
+ private RecyclerView.LayoutManager mLayoutManager;
public TestRecyclerView(Context context) {
super(context);
@@ -55,6 +57,16 @@
return adapter;
}
+ @Override
+ public void setLayoutManager(LayoutManager manager) {
+ mLayoutManager = manager;
+ }
+
+ @Override
+ public RecyclerView.LayoutManager getLayoutManager() {
+ return mLayoutManager;
+ }
+
public void setItems(List<String> modelIds) {
holders = new ArrayList<>();
for (String modelId: modelIds) {
@@ -64,8 +76,8 @@
}
public static TestRecyclerView create(List<String> modelIds) {
- final TestRecyclerView view = Mockito.mock(TestRecyclerView.class,
- Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
+ final TestRecyclerView view =
+ new TestRecyclerView(InstrumentationRegistry.getTargetContext());
view.holders = new ArrayList<>();
for (String modelId: modelIds) {
view.holders.add(new TestViewHolder(Views.createTestView()));
diff --git a/tests/common/com/android/documentsui/testing/TestResources.java b/tests/common/com/android/documentsui/testing/TestResources.java
index 907d923..0bd21de 100644
--- a/tests/common/com/android/documentsui/testing/TestResources.java
+++ b/tests/common/com/android/documentsui/testing/TestResources.java
@@ -85,10 +85,12 @@
return strings.get(id);
}
+ @Override
@NonNull
public final String getString(
@StringRes int id, Object... formatArgs) throws NotFoundException {
- return getString(id);
+ final String raw = getString(id);
+ return String.format(raw, formatArgs);
}
@Override
@@ -106,6 +108,7 @@
return null;
}
+ @Override
public final CharSequence getText(@StringRes int resId) {
return getString(resId);
}
diff --git a/tests/common/com/android/documentsui/testing/TestTimer.java b/tests/common/com/android/documentsui/testing/TestTimer.java
index e1a6610..89efb96 100644
--- a/tests/common/com/android/documentsui/testing/TestTimer.java
+++ b/tests/common/com/android/documentsui/testing/TestTimer.java
@@ -16,6 +16,7 @@
package com.android.documentsui.testing;
+import java.lang.IllegalStateException;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
@@ -28,6 +29,7 @@
*/
public class TestTimer extends Timer {
+ private boolean mIsCancelled;
private long mNow = 0;
private final LinkedList<Task> mTaskList = new LinkedList<>();
@@ -64,6 +66,7 @@
@Override
public void cancel() {
+ mIsCancelled = true;
mTaskList.clear();
}
@@ -114,6 +117,9 @@
}
public void scheduleAtTime(TimerTask task, long executeTime) {
+ if (mIsCancelled) {
+ throw new IllegalStateException("Timer already cancelled.");
+ }
Task testTimerTask = (Task) task;
testTimerTask.mExecuteTime = executeTime;
diff --git a/tests/functional/com/android/documentsui/FilesActivityUiTest.java b/tests/functional/com/android/documentsui/FilesActivityUiTest.java
index 87f3bac..90b6dd3 100644
--- a/tests/functional/com/android/documentsui/FilesActivityUiTest.java
+++ b/tests/functional/com/android/documentsui/FilesActivityUiTest.java
@@ -118,7 +118,7 @@
Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(
InspectorActivity.class.getName(), null, false);
bots.directory.selectDocument("file0.log");
- bots.main.clickActionItem("Properties");
+ bots.main.clickActionItem("Get info");
monitor.waitForActivityWithTimeout(TIMEOUT);
}
diff --git a/tests/functional/com/android/documentsui/InspectorUiTest.java b/tests/functional/com/android/documentsui/InspectorUiTest.java
index 724ba1d..a228de2 100644
--- a/tests/functional/com/android/documentsui/InspectorUiTest.java
+++ b/tests/functional/com/android/documentsui/InspectorUiTest.java
@@ -18,10 +18,12 @@
import android.content.Intent;
import android.net.Uri;
import android.provider.DocumentsContract;
+import android.support.test.filters.LargeTest;
import com.android.documentsui.bots.UiBot;
import com.android.documentsui.inspector.InspectorActivity;
+@LargeTest
public class InspectorUiTest extends ActivityTest<InspectorActivity> {
private static final String TEST_DOC_NAME = "test.txt";
@@ -56,11 +58,17 @@
bots.inspector.assertTitle("test.txt");
}
- public void testDisplayFileType() throws Exception {
+ public void testFolderDetails() throws Exception {
if (!features.isInspectorEnabled()) {
return;
}
- bots.inspector.assertRowPresent(getActivity().getString(R.string.sort_dimension_file_type),
- "vnd.android.document/directory", getActivity());
+ bots.inspector.assertRowEquals(
+ getActivity().getString(R.string.sort_dimension_file_type),
+ "Folder",
+ getActivity());
+ bots.inspector.assertRowEquals(
+ getActivity().getString(R.string.directory_items),
+ "4",
+ getActivity());
}
}
diff --git a/tests/res/raw/images.zip b/tests/res/raw/images.zip
new file mode 100644
index 0000000..b3013e9
--- /dev/null
+++ b/tests/res/raw/images.zip
Binary files differ
diff --git a/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java b/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java
index e094078..d9c5517 100644
--- a/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java
+++ b/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java
@@ -17,7 +17,7 @@
package com.android.documentsui;
import static junit.framework.Assert.assertTrue;
-
+import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import android.content.Intent;
@@ -31,8 +31,8 @@
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
-import com.android.documentsui.dirlist.DocumentDetails;
import com.android.documentsui.files.LauncherActivity;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
import com.android.documentsui.sorting.SortDimension;
import com.android.documentsui.sorting.SortModel;
import com.android.documentsui.testing.DocumentStackAsserts;
@@ -77,8 +77,7 @@
}
@Override
- public boolean openDocument(DocumentDetails doc, @ViewType int type,
- @ViewType int fallback) {
+ public boolean openItem(ItemDetails doc, @ViewType int type, @ViewType int fallback) {
throw new UnsupportedOperationException();
}
@@ -106,7 +105,8 @@
}
@Test
- public void testOpensContainerDocuments_jumpToNewLocation() throws Exception {
+ public void testOpensContainerDocuments_OpenFolderInSearch_JumpsToNewLocation()
+ throws Exception {
if (!mEnv.features.isLaunchToDocumentEnabled()) {
return;
}
@@ -114,6 +114,7 @@
mEnv.populateStack();
mEnv.searchViewManager.isSearching = true;
+ mEnv.docs.nextIsDocumentsUri = true;
mEnv.docs.nextPath = new Path(
TestProvidersAccess.HOME.rootId,
Arrays.asList(TestEnv.FOLDER_1.documentId, TestEnv.FOLDER_2.documentId));
@@ -124,15 +125,18 @@
mEnv.beforeAsserts();
assertEquals(mEnv.docs.nextPath.getPath().size(), mEnv.state.stack.size());
- assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.peek());
+ assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.pop());
+ assertEquals(TestEnv.FOLDER_1, mEnv.state.stack.pop());
}
@Test
- public void testOpensContainerDocuments_pushToRootDoc_NoFindPathSupport() throws Exception {
+ public void testOpensContainerDocuments_ClickFolderInSearch_PushToRootDoc_NoFindPathSupport()
+ throws Exception {
mEnv.populateStack();
mEnv.searchViewManager.isSearching = true;
+ mEnv.docs.nextIsDocumentsUri = true;
mEnv.docs.nextDocuments = Arrays.asList(TestEnv.FOLDER_1, TestEnv.FOLDER_2);
mHandler.openContainerDocument(TestEnv.FOLDER_2);
@@ -145,15 +149,42 @@
}
@Test
- public void testOpensDocument_AssertionErrorIfAlreadyInStack() throws Exception {
+ public void testOpensContainerDocuments_ClickArchiveInSearch_opensArchiveInArchiveProvider()
+ throws Exception {
+ if (!mEnv.features.isLaunchToDocumentEnabled()) {
+ return;
+ }
+
mEnv.populateStack();
- boolean threw = false;
+
+ mEnv.searchViewManager.isSearching = true;
+ mEnv.docs.nextIsDocumentsUri = true;
+ mEnv.docs.nextPath = new Path(
+ TestProvidersAccess.HOME.rootId,
+ Arrays.asList(TestEnv.FOLDER_1.documentId, TestEnv.FOLDER_2.documentId,
+ TestEnv.FILE_ARCHIVE.documentId));
+ mEnv.docs.nextDocuments = Arrays.asList(
+ TestEnv.FOLDER_1, TestEnv.FOLDER_2, TestEnv.FILE_ARCHIVE);
+ mEnv.docs.nextDocument = TestEnv.FILE_IN_ARCHIVE;
+
+ mHandler.openContainerDocument(TestEnv.FILE_ARCHIVE);
+
+ mEnv.beforeAsserts();
+
+ assertEquals(mEnv.docs.nextPath.getPath().size(), mEnv.state.stack.size());
+ assertEquals(TestEnv.FILE_IN_ARCHIVE, mEnv.state.stack.pop());
+ assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.pop());
+ assertEquals(TestEnv.FOLDER_1, mEnv.state.stack.pop());
+ }
+
+ @Test
+ public void testOpensDocument_ExceptionIfAlreadyInStack() throws Exception {
+ mEnv.populateStack();
try {
mEnv.state.stack.push(TestEnv.FOLDER_0);
- } catch (AssertionError e) {
- threw = true;
+ fail("Should have thrown IllegalArgumentException.");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(threw);
}
@Test
diff --git a/tests/unit/com/android/documentsui/DocsSelectionHelperTest.java b/tests/unit/com/android/documentsui/DocsSelectionHelperTest.java
new file mode 100644
index 0000000..845a5da
--- /dev/null
+++ b/tests/unit/com/android/documentsui/DocsSelectionHelperTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.RecyclerView.Adapter;
+
+import com.android.documentsui.DocsSelectionHelper.DelegateFactory;
+import com.android.documentsui.selection.DefaultSelectionHelper;
+import com.android.documentsui.selection.Selection;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+import com.android.documentsui.selection.SelectionHelper.StableIdProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for the specialized behaviors provided by DocsSelectionManager.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DocsSelectionHelperTest {
+
+ private DocsSelectionHelper mSelectionMgr;
+ private List<TestSelectionManager> mCreated;
+ private DelegateFactory mFactory;
+
+ @Before
+ public void setup() {
+ mCreated = new ArrayList<>();
+ mFactory = new DelegateFactory() {
+ @Override
+ TestSelectionManager create(
+ int mode,
+ Adapter<?> adapter,
+ StableIdProvider stableIds,
+ SelectionPredicate canSetState) {
+
+ TestSelectionManager mgr = new TestSelectionManager();
+ mCreated.add(mgr);
+ return mgr;
+ }
+ };
+
+ mSelectionMgr = new DocsSelectionHelper(mFactory, DefaultSelectionHelper.MODE_MULTIPLE);
+ }
+
+ @Test
+ public void testReset_CreatesNewInstances() {
+ mSelectionMgr.reset(null, null, null); // nulls are passed to factory. We ignore.
+ mSelectionMgr.reset(null, null, null); // nulls are passed to factory. We ignore.
+
+ assertCreated(2);
+ }
+
+ @Test
+ public void testReset_ClearsPreviousSelection() {
+ mSelectionMgr.reset(null, null, null); // nulls are passed to factory. We ignore.
+ mSelectionMgr.reset(null, null, null); // nulls are passed to factory. We ignore.
+
+ mCreated.get(0).assertCleared(true);
+ mCreated.get(1).assertCleared(false);
+ }
+
+ @Test
+ public void testReplaceSelection() {
+ mSelectionMgr.reset(null, null, null); // nulls are passed to factory. We ignore.
+
+ List<String> ids = new ArrayList<>();
+ ids.add("poodles");
+ ids.add("hammy");
+ mSelectionMgr.replaceSelection(ids);
+ mCreated.get(0).assertCleared(true);
+ mCreated.get(0).assertSelected("poodles", "hammy");
+ }
+
+ void assertCreated(int count) {
+ assertEquals(count, mCreated.size());
+ }
+
+ private static final class TestSelectionManager extends SelectionHelper {
+
+ private boolean mCleared;
+ private Map<String, Boolean> mSelected = new HashMap<>();
+
+ void assertCleared(boolean expected) {
+ assertEquals(expected, mCleared);
+ }
+
+ void assertSelected(String... expected) {
+ for (String id : expected) {
+ assertTrue(mSelected.containsKey(id));
+ assertTrue(mSelected.get(id));
+ }
+ assertEquals(expected.length, mSelected.size());
+ }
+
+ @Override
+ public void addObserver(SelectionObserver listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasSelection() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Selection getSelection() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void copySelection(Selection dest) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isSelected(String id) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void restoreSelection(Selection other) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean setItemsSelected(Iterable<String> ids, boolean selected) {
+ for (String id : ids) {
+ mSelected.put(id, selected);
+ }
+ return true;
+ }
+
+ @Override
+ public void clearSelection() {
+ mCleared = true;
+ }
+
+ @Override
+ public boolean select(String itemId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean deselect(String itemId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void startRange(int pos) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void extendRange(int pos) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void endRange() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isRangeActive() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void anchorRange(int position) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void extendProvisionalRange(int pos) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clearProvisionalSelection() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void mergeProvisionalSelection() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setProvisionalSelection(Set<String> newSelection) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/tests/unit/com/android/documentsui/FocusManagerTest.java b/tests/unit/com/android/documentsui/FocusManagerTest.java
index d4d7648..b386f82 100644
--- a/tests/unit/com/android/documentsui/FocusManagerTest.java
+++ b/tests/unit/com/android/documentsui/FocusManagerTest.java
@@ -16,15 +16,17 @@
package com.android.documentsui;
+import android.support.v7.widget.RecyclerView;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.documentsui.base.Features;
import com.android.documentsui.dirlist.TestData;
+import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.testing.TestModel;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.testing.SelectionManagers;
+import com.android.documentsui.testing.SelectionHelpers;
import com.android.documentsui.testing.TestFeatures;
+import com.android.documentsui.testing.TestGridLayoutManager;
import com.android.documentsui.testing.TestRecyclerView;
import java.util.ArrayList;
@@ -39,13 +41,17 @@
private FocusManager mManager;
private TestRecyclerView mView;
- private SelectionManager mSelectionMgr;
+ private TestGridLayoutManager mTestGridLayoutManager;
+ private SelectionHelper mSelectionMgr;
private TestFeatures mFeatures;
@Override
public void setUp() throws Exception {
mView = TestRecyclerView.create(ITEMS);
- mSelectionMgr = SelectionManagers.createTestInstance(ITEMS);
+ mTestGridLayoutManager = TestGridLayoutManager.create();
+ mView.setLayoutManager(mTestGridLayoutManager);
+
+ mSelectionMgr = SelectionHelpers.createTestInstance(ITEMS);
mFeatures = new TestFeatures();
mManager = new FocusManager(mFeatures, mSelectionMgr, null, null, 0)
.reset(mView, new TestModel(TEST_AUTHORITY, mFeatures));
@@ -68,13 +74,18 @@
public void testFocusDirectoryList_noItemsToFocus() {
mView = TestRecyclerView.create(new ArrayList<>());
mManager = new FocusManager(
- mFeatures, SelectionManagers.createTestInstance(), null, null, 0)
+ mFeatures, SelectionHelpers.createTestInstance(), null, null, 0)
.reset(mView, new TestModel(TEST_AUTHORITY, mFeatures));
assertFalse(mManager.focusDirectoryList());
}
+ public void testFocusDirectoryList_noVisibleItems() {
+ mTestGridLayoutManager.setFirstVisibleItemPosition(RecyclerView.NO_POSITION);
+ assertFalse(mManager.focusDirectoryList());
+ }
+
public void testFocusDirectoryList_hasSelection() {
- mSelectionMgr.toggleSelection("0");
+ mSelectionMgr.select("0");
assertFalse(mManager.focusDirectoryList());
}
}
diff --git a/tests/unit/com/android/documentsui/SharedInputHandlerTest.java b/tests/unit/com/android/documentsui/SharedInputHandlerTest.java
index 0f5c280..9c28094 100644
--- a/tests/unit/com/android/documentsui/SharedInputHandlerTest.java
+++ b/tests/unit/com/android/documentsui/SharedInputHandlerTest.java
@@ -27,8 +27,8 @@
import com.android.documentsui.base.Procedure;
import com.android.documentsui.dirlist.TestFocusHandler;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.testing.SelectionManagers;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.testing.SelectionHelpers;
import com.android.documentsui.testing.TestFeatures;
import org.junit.Before;
@@ -40,7 +40,7 @@
public class SharedInputHandlerTest {
private SharedInputHandler mSharedInputHandler;
- private SelectionManager mSelectionMgr = SelectionManagers.createTestInstance();
+ private SelectionHelper mSelectionMgr = SelectionHelpers.createTestInstance();
private TestFeatures mFeatures = new TestFeatures();
private TestFocusHandler mFocusHandler = new TestFocusHandler();
private boolean mDirPopHappened;
@@ -75,10 +75,10 @@
@Test
public void testBackButton_CancelsSearch() {
- mSelectionMgr.toggleSelection("1");
+ mSelectionMgr.select("1");
mSharedInputHandler = new SharedInputHandler(
new TestFocusHandler(),
- SelectionManagers.createTestInstance(),
+ SelectionHelpers.createTestInstance(),
() -> {
mCanceledSearch = true;
return true;
@@ -96,7 +96,7 @@
@Test
public void testBackButton_ClearsSelection() {
- mSelectionMgr.toggleSelection("1");
+ mSelectionMgr.select("1");
assertEquals(mSelectionMgr.getSelection().size(), 1);
KeyEvent backEvent =
new KeyEvent(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, 0, 0);
@@ -120,10 +120,10 @@
@Test
public void testEscButton_CancelsSearch() {
- mSelectionMgr.toggleSelection("1");
+ mSelectionMgr.select("1");
mSharedInputHandler = new SharedInputHandler(
new TestFocusHandler(),
- SelectionManagers.createTestInstance(),
+ SelectionHelpers.createTestInstance(),
() -> {
mCanceledSearch = true;
return true;
@@ -141,7 +141,7 @@
@Test
public void testEscButton_ClearsSelection() {
- mSelectionMgr.toggleSelection("1");
+ mSelectionMgr.select("1");
assertEquals(mSelectionMgr.getSelection().size(), 1);
KeyEvent escapeEvent =
new KeyEvent(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_ESCAPE, 0, 0);
diff --git a/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java b/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java
index 7b2504a..cc40e56 100644
--- a/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java
+++ b/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java
@@ -28,11 +28,11 @@
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
+import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.provider.DocumentsContract;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
@@ -264,4 +264,35 @@
client.release();
}
+
+ @Test
+ public void testGetDocumentMetadata() throws InterruptedException, RemoteException {
+ final Uri sourceUri = DocumentsContract.buildDocumentUri(
+ ResourcesProvider.AUTHORITY, "images.zip");
+ final Uri archiveUri = ArchivesProvider.buildUriForArchive(sourceUri,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+
+ final ContentResolver resolver = mContext.getContentResolver();
+ final ContentProviderClient client =
+ resolver.acquireUnstableContentProviderClient(archiveUri);
+
+ ArchivesProvider.acquireArchive(client, archiveUri);
+
+ Uri archivedImageUri = Uri.parse(
+ "content://com.android.documentsui.archives/document/content%3A%2F%2F"
+ + "com.android.documentsui.archives.resourcesprovider%2F"
+ + "document%2Fimages.zip%23268435456%23%2Ffreddy.jpg");
+
+ Bundle metadata = DocumentsContract.getDocumentMetadata(client, archivedImageUri);
+ assertNotNull(metadata);
+ Bundle exif = metadata.getBundle(DocumentsContract.METADATA_EXIF);
+ assertNotNull(exif);
+
+ assertEquals(3036, exif.getInt(ExifInterface.TAG_IMAGE_WIDTH));
+ assertEquals(4048, exif.getInt(ExifInterface.TAG_IMAGE_LENGTH));
+ assertEquals("Pixel", exif.getString(ExifInterface.TAG_MODEL));
+
+ ArchivesProvider.releaseArchive(client, archiveUri);
+ client.release();
+ }
}
diff --git a/tests/unit/com/android/documentsui/archives/ResourcesProvider.java b/tests/unit/com/android/documentsui/archives/ResourcesProvider.java
index 988b495..b9ddb92 100644
--- a/tests/unit/com/android/documentsui/archives/ResourcesProvider.java
+++ b/tests/unit/com/android/documentsui/archives/ResourcesProvider.java
@@ -56,9 +56,10 @@
private static final Map<String, Integer> RESOURCES = new HashMap<>();
static {
RESOURCES.put("archive.zip", R.raw.archive);
- RESOURCES.put("empty_dirs.zip", R.raw.empty_dirs);
- RESOURCES.put("no_dirs.zip", R.raw.no_dirs);
RESOURCES.put("broken.zip", R.raw.broken);
+ RESOURCES.put("empty_dirs.zip", R.raw.empty_dirs);
+ RESOURCES.put("images.zip", R.raw.images);
+ RESOURCES.put("no_dirs.zip", R.raw.no_dirs);
}
private ExecutorService mExecutor = null;
diff --git a/tests/unit/com/android/documentsui/dirlist/DirectoryAddonsAdapterTest.java b/tests/unit/com/android/documentsui/dirlist/DirectoryAddonsAdapterTest.java
index 68169bc..c25e43f 100644
--- a/tests/unit/com/android/documentsui/dirlist/DirectoryAddonsAdapterTest.java
+++ b/tests/unit/com/android/documentsui/dirlist/DirectoryAddonsAdapterTest.java
@@ -66,6 +66,17 @@
assertEquals(mEnv.model.getItemCount() + 1, mAdapter.getItemCount());
}
+ public void testGetPosition() {
+ mEnv.model.createFolder("a"); // id will be "1"...derived from insert position.
+ mEnv.model.createFile("b"); // id will be "2"
+ mEnv.model.update();
+
+ assertEquals(0, mAdapter.getPosition("1"));
+ // adapter inserts a view between item 0 and 1 to force layout
+ // break between folders and files. This is reflected by an offset position.
+ assertEquals(2, mAdapter.getPosition("2"));
+ }
+
// Tests that the item count is correct for a directory containing only subdirs.
public void testItemCount_allDirs() {
String[] names = {"Trader Joe's", "Alphabeta", "Lucky", "Vons", "Gelson's"};
@@ -187,8 +198,11 @@
}
private static class DummyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ @Override
public int getItemCount() { return 0; }
+ @Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {}
+ @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
diff --git a/tests/unit/com/android/documentsui/dirlist/DocumentHolderTest.java b/tests/unit/com/android/documentsui/dirlist/DocumentHolderTest.java
index 9d9256d..f2187e4 100644
--- a/tests/unit/com/android/documentsui/dirlist/DocumentHolderTest.java
+++ b/tests/unit/com/android/documentsui/dirlist/DocumentHolderTest.java
@@ -20,9 +20,9 @@
import android.database.Cursor;
import android.graphics.Rect;
import android.os.SystemClock;
+import android.support.test.filters.SmallTest;
import android.support.test.filters.Suppress;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -30,6 +30,7 @@
import android.view.MotionEvent.PointerProperties;
import com.android.documentsui.R;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
@SmallTest
public class DocumentHolderTest extends AndroidTestCase {
@@ -98,9 +99,9 @@
);
}
- private class TestListener implements DocumentHolder.KeyboardEventListener {
+ private class TestListener extends KeyboardEventListener {
@Override
- public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event) {
+ public boolean onKey(ItemDetails item, int keyCode, KeyEvent event) {
return false;
}
diff --git a/tests/unit/com/android/documentsui/dirlist/DragHostTest.java b/tests/unit/com/android/documentsui/dirlist/DragHostTest.java
index 4331ac4..7db69dc 100644
--- a/tests/unit/com/android/documentsui/dirlist/DragHostTest.java
+++ b/tests/unit/com/android/documentsui/dirlist/DragHostTest.java
@@ -28,10 +28,10 @@
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.files.TestActivity;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.testing.ClipDatas;
import com.android.documentsui.testing.DragEvents;
-import com.android.documentsui.testing.SelectionManagers;
+import com.android.documentsui.testing.SelectionHelpers;
import com.android.documentsui.testing.TestActionHandler;
import com.android.documentsui.testing.TestDragAndDropManager;
import com.android.documentsui.testing.TestEnv;
@@ -55,7 +55,7 @@
private TestDialogController mDialogs;
private DragHost<?> dragHost;
private TestDragAndDropManager mDragAndDropManager;
- private SelectionManager mSelectionMgr;
+ private SelectionHelper mSelectionMgr;
private boolean mIsDocumentView;
private DocumentHolder mNextDocumentHolder;
private DocumentInfo mNextDocumentInfo;
@@ -66,7 +66,7 @@
mActivity = TestActivity.create(mEnv);
mDialogs = new TestDialogController();
mDragAndDropManager = new TestDragAndDropManager();
- mSelectionMgr = SelectionManagers.createTestInstance(ITEMS);
+ mSelectionMgr = SelectionHelpers.createTestInstance(ITEMS);
mActionHandler = new TestActionHandler();
dragHost = new DragHost<>(
mActivity,
diff --git a/tests/unit/com/android/documentsui/dirlist/DragScrollListenerTest.java b/tests/unit/com/android/documentsui/dirlist/DragScrollListenerTest.java
index f779334..f0e9f9a 100644
--- a/tests/unit/com/android/documentsui/dirlist/DragScrollListenerTest.java
+++ b/tests/unit/com/android/documentsui/dirlist/DragScrollListenerTest.java
@@ -24,17 +24,14 @@
import android.view.View;
import com.android.documentsui.ItemDragListener;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollerCallbacks;
import com.android.documentsui.testing.DragEvents;
-import com.android.documentsui.testing.TestTimer;
import com.android.documentsui.testing.Views;
-import com.android.documentsui.ui.ViewAutoScroller.ScrollActionDelegate;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Timer;
-
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DragScrollListenerTest {
@@ -204,7 +201,7 @@
public void onDragEnded() {}
}
- private class TestScrollActionDelegate implements ScrollActionDelegate {
+ private class TestScrollActionDelegate extends ScrollerCallbacks {
private int mDy;
diff --git a/tests/unit/com/android/documentsui/dirlist/DragStartListenerTest.java b/tests/unit/com/android/documentsui/dirlist/DragStartListenerTest.java
index 635e249..faa86a3 100644
--- a/tests/unit/com/android/documentsui/dirlist/DragStartListenerTest.java
+++ b/tests/unit/com/android/documentsui/dirlist/DragStartListenerTest.java
@@ -18,7 +18,7 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static junit.framework.TestCase.fail;
+import static junit.framework.Assert.fail;
import android.provider.DocumentsContract;
import android.support.test.filters.SmallTest;
@@ -26,20 +26,22 @@
import android.view.MotionEvent;
import android.view.View;
-import com.android.documentsui.MenuManager;
+import com.android.documentsui.DocsSelectionHelper;
import com.android.documentsui.MenuManager.SelectionDetails;
import com.android.documentsui.base.DocumentInfo;
+import com.android.documentsui.base.Events;
import com.android.documentsui.base.Providers;
import com.android.documentsui.base.State;
-import com.android.documentsui.dirlist.DragStartListener.ActiveListener;
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.dirlist.DragStartListener.RuntimeDragStartListener;
+import com.android.documentsui.selection.MutableSelection;
import com.android.documentsui.selection.Selection;
+import com.android.documentsui.selection.TestItemDetailsLookup;
+import com.android.documentsui.testing.SelectionHelpers;
import com.android.documentsui.testing.TestDragAndDropManager;
-import com.android.documentsui.testing.TestEvent;
-import com.android.documentsui.testing.SelectionManagers;
+import com.android.documentsui.testing.TestEvents;
import com.android.documentsui.testing.TestSelectionDetails;
import com.android.documentsui.testing.Views;
+import com.android.internal.widget.RecyclerView;
import org.junit.Before;
import org.junit.Test;
@@ -51,18 +53,20 @@
@SmallTest
public class DragStartListenerTest {
- private ActiveListener mListener;
- private TestEvent.Builder mEvent;
- private SelectionManager mMultiSelectManager;
+ private RuntimeDragStartListener mListener;
+ private TestEvents.Builder mEvent;
+ private DocsSelectionHelper mSelectionMgr;
+ private TestItemDetailsLookup mDocLookup;
private SelectionDetails mSelectionDetails;
private String mViewModelId;
private TestDragAndDropManager mManager;
@Before
public void setUp() throws Exception {
- mMultiSelectManager = SelectionManagers.createTestInstance();
+ mSelectionMgr = SelectionHelpers.createTestInstance();
mManager = new TestDragAndDropManager();
mSelectionDetails = new TestSelectionDetails();
+ mDocLookup = new TestItemDetailsLookup();
DocumentInfo doc = new DocumentInfo();
doc.authority = Providers.AUTHORITY_STORAGE;
@@ -71,10 +75,12 @@
State state = new State();
state.stack.push(doc);
- mListener = new DragStartListener.ActiveListener(
+
+ mListener = new DragStartListener.RuntimeDragStartListener(
null, // icon helper
state,
- mMultiSelectManager,
+ mDocLookup,
+ mSelectionMgr,
mSelectionDetails,
// view finder
(float x, float y) -> {
@@ -86,21 +92,25 @@
},
// docInfo Converter
(Selection selection) -> {
- return new ArrayList<DocumentInfo>();
+ return new ArrayList<>();
},
mManager);
mViewModelId = "1234";
- mEvent = TestEvent.builder()
+ mDocLookup.initAt(1).setInItemDragRegion(true);
+ mEvent = TestEvents.builder()
.action(MotionEvent.ACTION_MOVE)
.mouse()
- .at(1)
- .inDragHotspot()
.primary();
}
@Test
+ public void testMouseEvent() {
+ assertTrue(Events.isMouseDragEvent(mEvent.build()));
+ }
+
+ @Test
public void testDragStarted_OnMouseMove() {
assertTrue(mListener.onMouseDragEvent(mEvent.build()));
mManager.startDragHandler.assertCalled();
@@ -115,15 +125,13 @@
@Test
public void testThrows_OnNonMouseMove() {
- TestEvent e = TestEvent.builder()
- .at(1)
- .action(MotionEvent.ACTION_MOVE).build();
- assertThrows(e);
+ assertThrows(mEvent.touch().build());
}
@Test
public void testThrows_OnNonPrimaryMove() {
- assertThrows(mEvent.pressButton(MotionEvent.BUTTON_PRIMARY).build());
+ mEvent.releaseButton(MotionEvent.BUTTON_PRIMARY);
+ assertThrows(mEvent.pressButton(MotionEvent.BUTTON_SECONDARY).build());
}
@Test
@@ -133,7 +141,8 @@
@Test
public void testThrows_WhenNotOnItem() {
- assertThrows(mEvent.at(-1).build());
+ mDocLookup.initAt(RecyclerView.NO_POSITION);
+ assertThrows(mEvent.build());
}
@Test
@@ -146,10 +155,10 @@
@Test
public void testDragStart_selectedItem() {
- Selection selection = new Selection();
+ MutableSelection selection = new MutableSelection();
selection.add("1234");
selection.add("5678");
- mMultiSelectManager.replaceSelection(selection);
+ mSelectionMgr.replaceSelection(selection);
selection = mListener.getSelectionToBeCopied("1234",
mEvent.action(MotionEvent.ACTION_MOVE).build());
@@ -160,23 +169,23 @@
@Test
public void testDragStart_newNonSelectedItem() {
- Selection selection = new Selection();
+ MutableSelection selection = new MutableSelection();
selection.add("5678");
- mMultiSelectManager.replaceSelection(selection);
+ mSelectionMgr.replaceSelection(selection);
selection = mListener.getSelectionToBeCopied("1234",
mEvent.action(MotionEvent.ACTION_MOVE).build());
assertTrue(selection.size() == 1);
assertTrue(selection.contains("1234"));
// After this, selection should be cleared
- assertFalse(mMultiSelectManager.hasSelection());
+ assertFalse(mSelectionMgr.hasSelection());
}
@Test
public void testCtrlDragStart_newNonSelectedItem() {
- Selection selection = new Selection();
+ MutableSelection selection = new MutableSelection();
selection.add("5678");
- mMultiSelectManager.replaceSelection(selection);
+ mSelectionMgr.replaceSelection(selection);
selection = mListener.getSelectionToBeCopied("1234",
mEvent.action(MotionEvent.ACTION_MOVE).ctrl().build());
@@ -185,10 +194,10 @@
assertTrue(selection.contains("5678"));
}
- private void assertThrows(InputEvent e) {
+ private void assertThrows(MotionEvent e) {
try {
- assertFalse(mListener.onMouseDragEvent(e));
+ mListener.onMouseDragEvent(e);
fail();
- } catch (AssertionError expected) {}
+ } catch (IllegalArgumentException expected) {}
}
}
diff --git a/tests/unit/com/android/documentsui/dirlist/KeyInputHandlerTest.java b/tests/unit/com/android/documentsui/dirlist/KeyInputHandlerTest.java
new file mode 100644
index 0000000..fdf9a59
--- /dev/null
+++ b/tests/unit/com/android/documentsui/dirlist/KeyInputHandlerTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.dirlist;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.annotation.Nullable;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.KeyEvent;
+
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.documentsui.selection.testing.SelectionPredicates;
+import com.android.documentsui.selection.testing.SelectionProbe;
+import com.android.documentsui.selection.testing.TestData;
+import com.android.documentsui.testing.SelectionHelpers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class KeyInputHandlerTest {
+
+ private static final List<String> ITEMS = TestData.create(100);
+
+ private KeyInputHandler mInputHandler;
+ private SelectionHelper mSelectionHelper;
+ private TestFocusHandler mFocusHandler;
+ private SelectionProbe mSelection;
+ private TestCallbacks mCallbacks;
+
+ @Before
+ public void setUp() {
+ mSelectionHelper = SelectionHelpers.createTestInstance(ITEMS);
+ mSelection = new SelectionProbe(mSelectionHelper);
+ mFocusHandler = new TestFocusHandler();
+ mCallbacks = new TestCallbacks();
+
+ mInputHandler = new KeyInputHandler(
+ mSelectionHelper,
+ SelectionPredicates.CAN_SET_ANYTHING,
+ mCallbacks);
+ }
+
+ @Test
+ public void testArrowKey_nonShiftClearsSelection() {
+ mSelectionHelper.select("11");
+
+ mFocusHandler.handleKey = true;
+ KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP);
+ mInputHandler.onKey(null, event.getKeyCode(), event);
+
+ mSelection.assertNoSelection();
+ }
+
+ private static final class TestCallbacks extends KeyInputHandler.Callbacks {
+
+ private @Nullable ItemDetails mActivated;
+
+ @Override
+ public boolean isInteractiveItem(ItemDetails item, KeyEvent e) {
+ return true;
+ }
+
+ @Override
+ public boolean onItemActivated(ItemDetails item, KeyEvent e) {
+ mActivated = item;
+ return false;
+ }
+
+ private void assertActivated(ItemDetails expected) {
+ assertEquals(expected, mActivated);
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_KeyboardTest.java b/tests/unit/com/android/documentsui/dirlist/UserInputHandler_KeyboardTest.java
deleted file mode 100644
index 97dd027..0000000
--- a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_KeyboardTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.dirlist;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.selection.SelectionProbe;
-import com.android.documentsui.testing.SelectionManagers;
-import com.android.documentsui.testing.TestActionHandler;
-import com.android.documentsui.testing.TestEvent;
-import com.android.documentsui.testing.TestEvent.Builder;
-import com.android.documentsui.testing.TestEventHandler;
-import com.android.documentsui.testing.TestPredicate;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class UserInputHandler_KeyboardTest {
-
- private static final List<String> ITEMS = TestData.create(100);
-
- private UserInputHandler<TestEvent> mInputHandler;
- private TestActionHandler mActionHandler;
- private TestFocusHandler mFocusHandler;
- private SelectionProbe mSelection;
-
- private TestPredicate<DocumentDetails> mCanSelect;
- private TestEventHandler<InputEvent> mRightClickHandler;
- private TestEventHandler<InputEvent> mDragAndDropHandler;
- private TestEventHandler<InputEvent> mGestureSelectHandler;
- private TestEventHandler<Void> mPerformHapticFeedback;
-
- private Builder mEvent;
-
- @Before
- public void setUp() {
- SelectionManager selectionMgr = SelectionManagers.createTestInstance(ITEMS);
-
- mActionHandler = new TestActionHandler();
- mSelection = new SelectionProbe(selectionMgr);
- mFocusHandler = new TestFocusHandler();
- mCanSelect = new TestPredicate<>();
- mRightClickHandler = new TestEventHandler<>();
- mDragAndDropHandler = new TestEventHandler<>();
- mGestureSelectHandler = new TestEventHandler<>();
-
- mInputHandler = new UserInputHandler<>(
- mActionHandler,
- mFocusHandler,
- selectionMgr,
- (MotionEvent event) -> {
- throw new UnsupportedOperationException("Not exercised in tests.");
- },
- mCanSelect,
- mRightClickHandler::accept,
- mDragAndDropHandler::accept,
- mGestureSelectHandler::accept,
- () -> mPerformHapticFeedback.accept(null));
-
- mEvent = TestEvent.builder().mouse().overDocIcon();
- }
-
- @Test
- public void testArrowKey_nonShiftClearsSelection() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(11).build());
- mSelection.assertSelection(11);
-
- mFocusHandler.handleKey = true;
- KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP);
- mInputHandler.onKey(null, event.getKeyCode(), event);
-
- mSelection.assertNoSelection();
- }
-}
\ No newline at end of file
diff --git a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_MouseTest.java b/tests/unit/com/android/documentsui/dirlist/UserInputHandler_MouseTest.java
deleted file mode 100644
index 2c916c6..0000000
--- a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_MouseTest.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.dirlist;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.v7.widget.RecyclerView;
-import android.view.MotionEvent;
-
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.selection.SelectionProbe;
-import com.android.documentsui.testing.SelectionManagers;
-import com.android.documentsui.testing.TestActionHandler;
-import com.android.documentsui.testing.TestEvent;
-import com.android.documentsui.testing.TestEvent.Builder;
-import com.android.documentsui.testing.TestEventHandler;
-import com.android.documentsui.testing.TestPredicate;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class UserInputHandler_MouseTest {
-
- private static final List<String> ITEMS = TestData.create(100);
-
- private UserInputHandler<TestEvent> mInputHandler;
- private TestActionHandler mActionHandler;
- private TestFocusHandler mFocusHandler;
- private SelectionProbe mSelection;
- private SelectionManager mSelectionMgr;
- private TestPredicate<DocumentDetails> mCanSelect;
- private TestEventHandler<InputEvent> mContextMenuClickHandler;
- private TestEventHandler<InputEvent> mDragAndDropHandler;
- private TestEventHandler<InputEvent> mGestureSelectHandler;
- private TestEventHandler<Void> mPerformHapticFeedback;
-
- private Builder mEvent;
-
- @Before
- public void setUp() {
-
- mSelectionMgr = SelectionManagers.createTestInstance(ITEMS);
- mActionHandler = new TestActionHandler();
-
- mSelection = new SelectionProbe(mSelectionMgr);
- mCanSelect = new TestPredicate<>();
- mContextMenuClickHandler = new TestEventHandler<>();
- mDragAndDropHandler = new TestEventHandler<>();
- mGestureSelectHandler = new TestEventHandler<>();
- mFocusHandler = new TestFocusHandler();
-
- mInputHandler = new UserInputHandler<>(
- mActionHandler,
- mFocusHandler,
- mSelectionMgr,
- (MotionEvent event) -> {
- throw new UnsupportedOperationException("Not exercised in tests.");
- },
- mCanSelect,
- mContextMenuClickHandler::accept,
- mDragAndDropHandler::accept,
- mGestureSelectHandler::accept,
- () -> mPerformHapticFeedback.accept(null));
-
- mEvent = TestEvent.builder().mouse().overDocIcon();
- }
-
- @Test
- public void testConfirmedClick_StartsSelection() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(11).build());
- mSelection.assertSelection(11);
- }
-
- @Test
- public void testClickOnIconWithExistingSelection_AddsToSelection() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(11).build());
- mInputHandler.onSingleTapUp(mEvent.at(10).build());
- mSelection.assertSelected(10, 11);
- }
-
- @Test
- public void testClickOnIconOfSelectedItem_RemovesFromSelection() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(8).build());
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
- mSelection.assertSelected(8, 9, 10, 11);
-
- mInputHandler.onSingleTapUp(mEvent.at(9).unshift().build());
- mSelection.assertSelected(8, 10, 11);
- }
-
- @Test
- public void testRightClickDown_StartsContextMenu() {
- mInputHandler.onDown(mEvent.secondary().build());
- mContextMenuClickHandler.assertLastArgument(mEvent.secondary().build());
- }
-
- @Test
- public void testAltClickDown_StartsContextMenu() {
- mInputHandler.onDown(mEvent.primary().alt().build());
- mContextMenuClickHandler.assertLastArgument(mEvent.primary().alt().build());
- }
-
- @Test
- public void testScroll_shouldTrap() {
- assertTrue(mInputHandler.onScroll(mEvent.at(0).action(MotionEvent.ACTION_MOVE).primary().build()));
- }
-
- @Test
- public void testScroll_NoTrapForTwoFinger() {
- assertFalse(mInputHandler.onScroll(mEvent.at(0).action(MotionEvent.ACTION_MOVE).build()));
- }
-
- @Test
- public void testUnconfirmedCtrlClick_AddsToExistingSelection() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
-
- mInputHandler.onSingleTapUp(mEvent.at(11).ctrl().build());
- mSelection.assertSelection(7, 11);
- }
-
- @Test
- public void testUnconfirmedShiftClick_ExtendsSelection() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
-
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
- mSelection.assertSelection(7, 8, 9, 10, 11);
- }
-
- @Test
- public void testConfirmedShiftClick_ExtendsSelectionFromOriginFocus() {
- mFocusHandler.focusPos = 7;
- mFocusHandler.focusModelId = "7";
- // This is a hack-y test, since the real FocusManager would've set range begin itself.
- mSelectionMgr.setSelectionRangeBegin(7);
- mSelection.assertNoSelection();
-
- mInputHandler.onSingleTapConfirmed(mEvent.at(11).shift().build());
- mSelection.assertSelection(7, 8, 9, 10, 11);
- }
-
- @Test
- public void testUnconfirmedShiftClick_RotatesAroundOrigin() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
-
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
- mSelection.assertSelection(7, 8, 9, 10, 11);
-
- mInputHandler.onSingleTapUp(mEvent.at(5).shift().build());
- mSelection.assertSelection(5, 6, 7);
- mSelection.assertNotSelected(8, 9, 10, 11);
- }
-
- @Test
- public void testUnconfirmedShiftCtrlClick_Combination() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
-
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
- mSelection.assertSelection(7, 8, 9, 10, 11);
-
- mInputHandler.onSingleTapUp(mEvent.at(5).unshift().ctrl().build());
-
- mSelection.assertSelection(5, 7, 8, 9, 10, 11);
- }
-
- @Test
- public void testUnconfirmedShiftCtrlClick_ShiftTakesPriority() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
-
- mInputHandler.onSingleTapUp(mEvent.at(11).ctrl().shift().build());
- mSelection.assertSelection(7, 8, 9, 10, 11);
- }
-
- // TODO: Add testSpaceBar_Previews, but we need to set a system property
- // to have a deterministic state.
-
- @Test
- public void testDoubleClick_Opens() {
- mInputHandler.onDoubleTap(mEvent.at(11).build());
- mActionHandler.open.assertLastArgument(mEvent.build().getDocumentDetails());
- }
-
- @Test
- public void testMiddleClick_DoesNothing() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(11).tertiary().build());
- mSelection.assertNoSelection();
- }
-
- @Test
- public void testClickOff_ClearsSelection() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(11).build());
- mInputHandler.onSingleTapUp(mEvent.at(RecyclerView.NO_POSITION).build());
- mSelection.assertNoSelection();
- }
-
- @Test
- public void testClick_Focuses() {
- int id = 11;
- mInputHandler.onSingleTapConfirmed(mEvent.at(id).notOverDocIcon().build());
- assertTrue(mFocusHandler.getFocusModelId().equals(Integer.toString(id)));
- }
-
- @Test
- public void testClickOff_ClearsFocus() {
- int id = 11;
- mInputHandler.onSingleTapConfirmed(mEvent.at(id).notOverDocIcon().build());
- assertTrue(mFocusHandler.hasFocusedItem());
- mInputHandler.onSingleTapUp(mEvent.at(RecyclerView.NO_POSITION).build());
- assertFalse(mFocusHandler.hasFocusedItem());
- }
-
- @Test
- public void testClickOffSelection_RemovesSelectionAndFocuses() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(1).build());
- mInputHandler.onSingleTapUp(mEvent.at(5).shift().build());
- mSelection.assertSelection(1, 2, 3, 4, 5);
-
- int id = 11;
- mInputHandler.onSingleTapUp(mEvent.at(id).unshift().notOverDocIcon().build());
- assertTrue(mFocusHandler.getFocusModelId().equals(Integer.toString(id)));
- mSelection.assertNoSelection();
- }
-}
diff --git a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_RangeTest.java b/tests/unit/com/android/documentsui/dirlist/UserInputHandler_RangeTest.java
deleted file mode 100644
index 7ce85e1..0000000
--- a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_RangeTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.dirlist;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.MotionEvent;
-
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.selection.SelectionProbe;
-import com.android.documentsui.testing.SelectionManagers;
-import com.android.documentsui.testing.TestActionHandler;
-import com.android.documentsui.testing.TestEvent;
-import com.android.documentsui.testing.TestEvent.Builder;
-import com.android.documentsui.testing.TestEventHandler;
-import com.android.documentsui.testing.TestPredicate;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-/**
- * UserInputHandler / MultiSelectManager integration test covering the shared
- * responsibility of range selection.
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class UserInputHandler_RangeTest {
-
- private static final List<String> ITEMS = TestData.create(100);
-
- private UserInputHandler<TestEvent> mInputHandler;
- private TestActionHandler mActionHandler;
-
- private SelectionProbe mSelection;
- private TestFocusHandler mFocusHandler;
- private TestPredicate<DocumentDetails> mCanSelect;
- private TestEventHandler<InputEvent> mRightClickHandler;
- private TestEventHandler<InputEvent> mDragAndDropHandler;
- private TestEventHandler<InputEvent> mGestureSelectHandler;
- private TestEventHandler<Void> mPerformHapticFeedback;
- private Builder mEvent;
-
- @Before
- public void setUp() {
-
- SelectionManager selectionMgr = SelectionManagers.createTestInstance(ITEMS);
- mActionHandler = new TestActionHandler();
- mFocusHandler = new TestFocusHandler();
- mSelection = new SelectionProbe(selectionMgr);
- mCanSelect = new TestPredicate<>();
- mRightClickHandler = new TestEventHandler<>();
- mDragAndDropHandler = new TestEventHandler<>();
- mGestureSelectHandler = new TestEventHandler<>();
-
- mInputHandler = new UserInputHandler<>(
- mActionHandler,
- mFocusHandler,
- selectionMgr,
- (MotionEvent event) -> {
- throw new UnsupportedOperationException("Not exercised in tests.");
- },
- mCanSelect,
- mRightClickHandler::accept,
- mDragAndDropHandler::accept,
- mGestureSelectHandler::accept,
- () -> mPerformHapticFeedback.accept(null));
-
- mEvent = TestEvent.builder().mouse().overDocIcon();
- }
-
- @Test
- public void testExtendRange() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
- mSelection.assertRangeSelection(7, 11);
- }
-
- @Test
- public void testExtendRangeContinues() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
- mInputHandler.onSingleTapUp(mEvent.at(21).shift().build());
- mSelection.assertRangeSelection(7, 21);
- }
-
- @Test
- public void testMultipleContiguousRanges() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
-
- // click without shift sets a new range start point.
- mInputHandler.onSingleTapUp(mEvent.at(20).unshift().notOverDocIcon().build());
- mInputHandler.onSingleTapConfirmed(mEvent.at(20).notOverDocIcon().build());
- mFocusHandler.focusPos = 20;
- mInputHandler.onSingleTapUp(mEvent.at(25).shift().notOverDocIcon().build());
- mInputHandler.onSingleTapConfirmed(mEvent.at(25).shift().notOverDocIcon().build());
-
- mSelection.assertRangeNotSelected(7, 11);
- mSelection.assertRangeSelected(20, 25);
- mSelection.assertSelectionSize(6);
- }
-
- @Test
- public void testReducesSelectionRange() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
- mInputHandler.onSingleTapUp(mEvent.at(17).shift().build());
- mInputHandler.onSingleTapUp(mEvent.at(10).shift().build());
- mSelection.assertRangeSelection(7, 10);
- }
-
- @Test
- public void testReducesSelectionRange_Reverse() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(17).build());
- mInputHandler.onSingleTapUp(mEvent.at(7).shift().build());
- mInputHandler.onSingleTapUp(mEvent.at(14).shift().build());
- mSelection.assertRangeSelection(14, 17);
- }
-
- @Test
- public void testExtendsRange_Reverse() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(12).build());
- mInputHandler.onSingleTapUp(mEvent.at(5).shift().build());
- mSelection.assertRangeSelection(5, 12);
- }
-
- @Test
- public void testExtendsRange_ReversesAfterForwardClick() {
- mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
- mInputHandler.onSingleTapUp(mEvent.at(11).shift().build());
- mInputHandler.onSingleTapUp(mEvent.at(0).shift().build());
- mSelection.assertRangeSelection(0, 7);
- }
-
- @Test
- public void testRightClickEstablishesRange() {
-
- TestEvent fistClick = mEvent.at(7).secondary().build();
- mInputHandler.onDown(fistClick);
- // This next method call simulates the behavior of the system event dispatch code.
- // UserInputHandler depends on a specific sequence of events for internal
- // state to remain valid. It's not an awesome arrangement, but it is currently
- // necessary.
- //
- // See: UserInputHandler.MouseDelegate#mHandledOnDown;
- mInputHandler.onSingleTapUp(fistClick);
-
- // Now we can send a subsequent event that should extend selection.
- TestEvent secondClick = mEvent.at(11).primary().shift().build();
- mInputHandler.onDown(secondClick);
- mInputHandler.onSingleTapUp(secondClick);
-
- mSelection.assertRangeSelection(7, 11);
- }
-}
diff --git a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_TouchTest.java b/tests/unit/com/android/documentsui/dirlist/UserInputHandler_TouchTest.java
deleted file mode 100644
index 86d49d0..0000000
--- a/tests/unit/com/android/documentsui/dirlist/UserInputHandler_TouchTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.dirlist;
-
-import static org.junit.Assert.assertFalse;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.v7.widget.RecyclerView;
-import android.view.MotionEvent;
-
-import com.android.documentsui.base.Events.InputEvent;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.selection.SelectionProbe;
-import com.android.documentsui.testing.SelectionManagers;
-import com.android.documentsui.testing.TestActionHandler;
-import com.android.documentsui.testing.TestEvent;
-import com.android.documentsui.testing.TestEvent.Builder;
-import com.android.documentsui.testing.TestEventHandler;
-import com.android.documentsui.testing.TestPredicate;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public final class UserInputHandler_TouchTest {
-
- private static final List<String> ITEMS = TestData.create(100);
-
- private UserInputHandler<TestEvent> mInputHandler;
- private TestActionHandler mActionHandler;
-
- private SelectionProbe mSelection;
- private TestPredicate<DocumentDetails> mCanSelect;
- private TestEventHandler<InputEvent> mRightClickHandler;
- private TestEventHandler<InputEvent> mDragAndDropHandler;
- private TestEventHandler<InputEvent> mGestureSelectHandler;
- private TestEventHandler<Void> mPerformHapticFeedback;
-
- private Builder mEvent;
-
- @Before
- public void setUp() {
- SelectionManager selectionMgr = SelectionManagers.createTestInstance(ITEMS);
-
- mActionHandler = new TestActionHandler();
-
- mSelection = new SelectionProbe(selectionMgr);
- mCanSelect = new TestPredicate<>();
- mRightClickHandler = new TestEventHandler<>();
- mDragAndDropHandler = new TestEventHandler<>();
- mGestureSelectHandler = new TestEventHandler<>();
- mPerformHapticFeedback = new TestEventHandler<>();
-
- mInputHandler = new UserInputHandler<>(
- mActionHandler,
- new TestFocusHandler(),
- selectionMgr,
- (MotionEvent event) -> {
- throw new UnsupportedOperationException("Not exercised in tests.");
- },
- mCanSelect,
- mRightClickHandler::accept,
- mDragAndDropHandler::accept,
- mGestureSelectHandler::accept,
- () -> mPerformHapticFeedback.accept(null));
-
- mEvent = TestEvent.builder();
- }
-
- @Test
- public void testTap_ActivatesWhenNoExistingSelection() {
- mInputHandler.onSingleTapUp(mEvent.at(11).build());
- mActionHandler.open.assertLastArgument(mEvent.build().getDocumentDetails());
- }
-
- @Test
- public void testScroll_shouldNotBeTrapped() {
- assertFalse(mInputHandler.onScroll(mEvent.build()));
- }
-
- @Test
- public void testLongPress_StartsSelectionMode() {
- mCanSelect.nextReturn(true);
- TestEvent event = mEvent.at(7).build();
- mInputHandler.onLongPress(event);
- mSelection.assertSelection(7);
- mPerformHapticFeedback.assertCalled();
- }
-
- @Test
- public void testLongPress_SecondPressAddsSelection() {
- mCanSelect.nextReturn(true);
- TestEvent event1 = mEvent.at(7).build();
- TestEvent event2 = mEvent.at(99).build();
- TestEvent event3 = mEvent.at(13).build();
- mInputHandler.onLongPress(event1);
- mPerformHapticFeedback.assertCalled();
- mPerformHapticFeedback.reset();
- mInputHandler.onLongPress(event2);
- mPerformHapticFeedback.assertCalled();
- mPerformHapticFeedback.reset();
- mInputHandler.onLongPress(event3);
- mPerformHapticFeedback.assertCalled();
- mPerformHapticFeedback.reset();
- mSelection.assertSelection(7, 13, 99);
- }
-
- @Test
- public void testTap_UnselectsSelectedItem() {
- mInputHandler.onLongPress(mEvent.at(7).build());
- mInputHandler.onSingleTapUp(mEvent.at(7).build());
- mSelection.assertNoSelection();
- }
-
- @Test
- public void testTapOff_ClearsSelection() {
- mInputHandler.onLongPress(mEvent.at(7).build());
- mInputHandler.onSingleTapUp(mEvent.at(11).build());
- mInputHandler.onSingleTapUp(mEvent.at(RecyclerView.NO_POSITION).build());
- mSelection.assertNoSelection();
- }
-}
diff --git a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
index 9b35ee1..34c3142 100644
--- a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
+++ b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
@@ -17,9 +17,12 @@
package com.android.documentsui.files;
import static com.android.documentsui.testing.IntentAsserts.assertHasAction;
+import static com.android.documentsui.testing.IntentAsserts.assertHasData;
+import static com.android.documentsui.testing.IntentAsserts.assertHasExtra;
import static com.android.documentsui.testing.IntentAsserts.assertHasExtraIntent;
import static com.android.documentsui.testing.IntentAsserts.assertHasExtraList;
import static com.android.documentsui.testing.IntentAsserts.assertHasExtraUri;
+import static com.android.documentsui.testing.IntentAsserts.assertTargetsComponent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -35,8 +38,8 @@
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Path;
-import android.support.test.filters.MediumTest;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.Pair;
import android.view.DragEvent;
@@ -49,6 +52,7 @@
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
+import com.android.documentsui.inspector.InspectorActivity;
import com.android.documentsui.testing.ClipDatas;
import com.android.documentsui.testing.DocumentStackAsserts;
import com.android.documentsui.testing.Roots;
@@ -56,8 +60,10 @@
import com.android.documentsui.testing.TestDocumentClipper;
import com.android.documentsui.testing.TestDragAndDropManager;
import com.android.documentsui.testing.TestEnv;
+import com.android.documentsui.testing.TestFeatures;
import com.android.documentsui.testing.TestProvidersAccess;
import com.android.documentsui.ui.TestDialogController;
+import com.android.internal.util.Preconditions;
import org.junit.Before;
import org.junit.Test;
@@ -76,11 +82,13 @@
private ActionHandler<TestActivity> mHandler;
private TestDocumentClipper mClipper;
private TestDragAndDropManager mDragAndDropManager;
+ private TestFeatures mFeatures;
private boolean refreshAnswer = false;
@Before
public void setUp() {
- mEnv = TestEnv.create();
+ mFeatures = new TestFeatures();
+ mEnv = TestEnv.create(mFeatures);
mActivity = TestActivity.create(mEnv);
mActionModeAddons = new TestActionModeAddons();
mDialogs = new TestDialogController();
@@ -326,6 +334,15 @@
}
@Test
+ public void testDocumentPicked_Home_SendsActionViewForApks() throws Exception {
+ mActivity.currentRoot = TestProvidersAccess.HOME;
+
+ mHandler.openDocument(TestEnv.FILE_APK, ActionHandler.VIEW_TYPE_PREVIEW,
+ ActionHandler.VIEW_TYPE_REGULAR);
+ mActivity.assertActivityStarted(Intent.ACTION_VIEW);
+ }
+
+ @Test
public void testDocumentPicked_Downloads_ManagesPartialFiles() throws Exception {
mActivity.currentRoot = TestProvidersAccess.DOWNLOADS;
@@ -534,6 +551,78 @@
mActivity.refreshCurrentRootAndDirectory.assertNotCalled();
}
+ @Test
+ public void testShowInspector() throws Exception {
+ mHandler.showInspector(TestEnv.FILE_GIF);
+
+ mActivity.startActivity.assertCalled();
+ Intent intent = mActivity.startActivity.getLastValue();
+ assertTargetsComponent(intent, InspectorActivity.class);
+ assertHasData(intent, TestEnv.FILE_GIF.derivedUri);
+
+ // should only send this under especial circumstances. See test below.
+ assertFalse(intent.getExtras().containsKey(Intent.EXTRA_TITLE));
+ }
+
+ @Test
+ public void testShowInspector_DebugDisabled() throws Exception {
+ mFeatures.debugSupport = false;
+
+ mHandler.showInspector(TestEnv.FILE_GIF);
+ Intent intent = mActivity.startActivity.getLastValue();
+
+ assertHasExtra(intent, Shared.EXTRA_SHOW_DEBUG);
+ assertFalse(intent.getExtras().getBoolean(Shared.EXTRA_SHOW_DEBUG));
+ }
+
+ @Test
+ public void testShowInspector_DebugEnabled() throws Exception {
+ mFeatures.debugSupport = true;
+
+ mHandler.showInspector(TestEnv.FILE_GIF);
+ Intent intent = mActivity.startActivity.getLastValue();
+
+ assertHasExtra(intent, Shared.EXTRA_SHOW_DEBUG);
+ assertTrue(intent.getExtras().getBoolean(Shared.EXTRA_SHOW_DEBUG));
+ }
+
+ @Test
+ public void testShowInspector_OverridesRootDocumentName() throws Exception {
+ mActivity.currentRoot = TestProvidersAccess.PICKLES;
+ mEnv.populateStack();
+
+ // Verify test setup is correct, but not an assert related to the logic of our test.
+ Preconditions.checkState(mEnv.state.stack.size() == 1);
+ Preconditions.checkNotNull(mEnv.state.stack.peek());
+
+ DocumentInfo rootDoc = mEnv.state.stack.peek();
+ rootDoc.displayName = "poodles";
+
+ mHandler.showInspector(rootDoc);
+ Intent intent = mActivity.startActivity.getLastValue();
+ assertEquals(
+ TestProvidersAccess.PICKLES.title,
+ intent.getExtras().getString(Intent.EXTRA_TITLE));
+ }
+
+ @Test
+ public void testShowInspector_OverridesRootDocumentNameX() throws Exception {
+ mActivity.currentRoot = TestProvidersAccess.PICKLES;
+ mEnv.populateStack();
+ mEnv.state.stack.push(TestEnv.FOLDER_2);
+
+ // Verify test setup is correct, but not an assert related to the logic of our test.
+ Preconditions.checkState(mEnv.state.stack.size() == 2);
+ Preconditions.checkNotNull(mEnv.state.stack.peek());
+
+ DocumentInfo rootDoc = mEnv.state.stack.peek();
+ rootDoc.displayName = "poodles";
+
+ mHandler.showInspector(rootDoc);
+ Intent intent = mActivity.startActivity.getLastValue();
+ assertFalse(intent.getExtras().containsKey(Intent.EXTRA_TITLE));
+ }
+
private void assertRootPicked(Uri expectedUri) throws Exception {
mEnv.beforeAsserts();
diff --git a/tests/unit/com/android/documentsui/files/MenuManagerTest.java b/tests/unit/com/android/documentsui/files/MenuManagerTest.java
index 3420210..3a42015 100644
--- a/tests/unit/com/android/documentsui/files/MenuManagerTest.java
+++ b/tests/unit/com/android/documentsui/files/MenuManagerTest.java
@@ -32,8 +32,8 @@
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.TestContext;
import com.android.documentsui.dirlist.TestData;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.testing.SelectionManagers;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.testing.SelectionHelpers;
import com.android.documentsui.testing.TestDirectoryDetails;
import com.android.documentsui.testing.TestEnv;
import com.android.documentsui.testing.TestFeatures;
@@ -66,8 +66,9 @@
private TestMenuItem dirRename;
private TestMenuItem dirDelete;
private TestMenuItem dirViewInOwner;
- private TestMenuItem dirOpenInNewWindow;
private TestMenuItem dirPasteIntoFolder;
+ private TestMenuItem dirInspect;
+ private TestMenuItem dirOpenInNewWindow;
/* Root List Context Menu items */
private TestMenuItem rootEjectRoot;
@@ -99,6 +100,7 @@
private TestMenuItem optionSelectAll;
private TestMenuItem optionAdvanced;
private TestMenuItem optionSettings;
+ private TestMenuItem optionInspector;
private TestFeatures features;
private TestSelectionDetails selectionDetails;
@@ -110,11 +112,13 @@
private State state = new State();
private MenuManager mgr;
private TestActivity activity = TestActivity.create(TestEnv.create());
- private SelectionManager selectionManager;
+ private SelectionHelper selectionManager;
@Before
public void setUp() {
testMenu = TestMenu.create();
+
+ // The context menu on anything in DirectoryList (including no selection).
dirShare = testMenu.findItem(R.id.dir_menu_share);
dirOpen = testMenu.findItem(R.id.dir_menu_open);
dirOpenWith = testMenu.findItem(R.id.dir_menu_open_with);
@@ -126,14 +130,16 @@
dirRename = testMenu.findItem(R.id.dir_menu_rename);
dirDelete = testMenu.findItem(R.id.dir_menu_delete);
dirViewInOwner = testMenu.findItem(R.id.dir_menu_view_in_owner);
- dirOpenInNewWindow = testMenu.findItem(R.id.dir_menu_open_in_new_window);
dirPasteIntoFolder = testMenu.findItem(R.id.dir_menu_paste_into_folder);
+ dirInspect = testMenu.findItem(R.id.dir_menu_inspect);
+ dirOpenInNewWindow = testMenu.findItem(R.id.dir_menu_open_in_new_window);
rootEjectRoot = testMenu.findItem(R.id.root_menu_eject_root);
rootOpenInNewWindow = testMenu.findItem(R.id.root_menu_open_in_new_window);
rootPasteIntoFolder = testMenu.findItem(R.id.root_menu_paste_into_folder);
rootSettings = testMenu.findItem(R.id.root_menu_settings);
+ // Menu actions (including overflow) when action mode *is* active.
actionModeOpen = testMenu.findItem(R.id.action_menu_open);
actionModeOpenWith = testMenu.findItem(R.id.action_menu_open_with);
actionModeShare = testMenu.findItem(R.id.action_menu_share);
@@ -144,9 +150,10 @@
actionModeMoveTo = testMenu.findItem(R.id.action_menu_move_to);
actionModeCompress = testMenu.findItem(R.id.action_menu_compress);
actionModeRename = testMenu.findItem(R.id.action_menu_rename);
- actionModeInspector = testMenu.findItem(R.id.action_menu_inspector);
+ actionModeInspector = testMenu.findItem(R.id.action_menu_inspect);
actionModeViewInOwner = testMenu.findItem(R.id.action_menu_view_in_owner);
+ // Menu actions (including overflow) when action mode is not active.
optionSearch = testMenu.findItem(R.id.option_menu_search);
optionDebug = testMenu.findItem(R.id.option_menu_debug);
optionGrid = testMenu.findItem(R.id.option_menu_grid);
@@ -156,6 +163,7 @@
optionSelectAll = testMenu.findItem(R.id.option_menu_select_all);
optionAdvanced = testMenu.findItem(R.id.option_menu_advanced);
optionSettings = testMenu.findItem(R.id.option_menu_settings);
+ optionInspector = testMenu.findItem(R.id.option_menu_inspect);
features = new TestFeatures();
@@ -168,8 +176,8 @@
dirDetails = new TestDirectoryDetails();
testSearchManager = new TestSearchViewManager();
preferences = new TestScopedPreferences();
- selectionManager = SelectionManagers.createTestInstance(TestData.create(1));
- selectionManager.toggleSelection("0");
+ selectionManager = SelectionHelpers.createTestInstance(TestData.create(1));
+ selectionManager.select("0");
mgr = new MenuManager(
features,
@@ -271,6 +279,7 @@
@Test
public void testActionsMenu_canViewInOwner() {
+ activity.resources.strings.put(R.string.menu_view_in_owner, "Insert name here! %s");
selectionDetails.canViewInOwner = true;
mgr.updateActionMenu(testMenu, selectionDetails);
@@ -351,6 +360,26 @@
}
@Test
+ public void testActionMenu_InspectorEnabledForSingleSelection() {
+ features.inspector = true;
+ selectionDetails.size = 1;
+ mgr.updateActionMenu(testMenu, selectionDetails);
+
+ actionModeInspector.assertVisible();
+ actionModeInspector.assertEnabled();
+ }
+
+ @Test
+ public void testActionMenu_InspectorDisabledForMultiSelection() {
+ features.inspector = true;
+ selectionDetails.size = 2;
+ mgr.updateActionMenu(testMenu, selectionDetails);
+
+ actionModeInspector.assertVisible();
+ actionModeInspector.assertDisabled();
+ }
+
+ @Test
public void testOptionMenu() {
mgr.updateOptionMenu(testMenu);
@@ -388,6 +417,27 @@
}
@Test
+ public void testOptionMenu_InspectorAvailable() {
+ features.inspector = true;
+ mgr.updateOptionMenu(testMenu);
+ optionInspector.assertVisible();
+ optionInspector.assertEnabled();
+ }
+
+ @Test
+ public void testOptionMenu_InspectorDisabledInRecentsFolder() {
+ features.inspector = true;
+
+ // synthesize a fake recents root. Not setting an authority or id == recents.
+ RootInfo recents = new RootInfo();
+ assert recents.isRecents();
+ state.stack.changeRoot(recents);
+ mgr.updateOptionMenu(testMenu);
+ optionInspector.assertVisible();
+ optionInspector.assertDisabled();
+ }
+
+ @Test
public void testInflateContextMenu_Files() {
TestMenuInflater inflater = new TestMenuInflater();
@@ -560,6 +610,13 @@
}
@Test
+ public void testContextMenu_CanInspectContainer() {
+ mgr.updateContextMenuForContainer(testMenu);
+ dirInspect.assertVisible();
+ dirInspect.assertEnabled();
+ }
+
+ @Test
public void testContextMenu_OnWritableDirectory_NothingToPaste() {
selectionDetails.canPasteInto = true;
selectionDetails.size = 1;
@@ -624,6 +681,14 @@
}
@Test
+ public void testContextMenu_CanInspectSingleSelection() {
+ selectionDetails.size = 1;
+ mgr.updateContextMenuForFiles(testMenu, selectionDetails);
+ dirInspect.assertVisible();
+ dirInspect.assertEnabled();
+ }
+
+ @Test
public void testRootContextMenu() {
testRootInfo.flags = Root.FLAG_SUPPORTS_CREATE;
diff --git a/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java b/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java
index 8fd130c..ad87726 100644
--- a/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java
+++ b/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java
@@ -59,9 +59,10 @@
Set<String> features = new HashSet<>(
Arrays.asList(intent.getStringArrayExtra(Intent.EXTRA_QUICK_VIEW_FEATURES)));
- assertEquals("Unexpected features set: " + features, 5, features.size());
+ assertEquals("Unexpected features set: " + features, 6, features.size());
assertTrue(features.contains(QuickViewConstants.FEATURE_VIEW));
assertTrue(features.contains(QuickViewConstants.FEATURE_EDIT));
+ assertTrue(features.contains(QuickViewConstants.FEATURE_DELETE));
assertTrue(features.contains(QuickViewConstants.FEATURE_SEND));
assertTrue(features.contains(QuickViewConstants.FEATURE_DOWNLOAD));
assertTrue(features.contains(QuickViewConstants.FEATURE_PRINT));
diff --git a/tests/unit/com/android/documentsui/inspector/DocumentLoaderTest.java b/tests/unit/com/android/documentsui/inspector/DocumentLoaderTest.java
index 7c9bb02..cd487b6 100644
--- a/tests/unit/com/android/documentsui/inspector/DocumentLoaderTest.java
+++ b/tests/unit/com/android/documentsui/inspector/DocumentLoaderTest.java
@@ -25,7 +25,7 @@
import com.android.documentsui.InspectorProvider;
import android.test.suitebuilder.annotation.MediumTest;
import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.inspector.InspectorController.Loader;
+import com.android.documentsui.inspector.InspectorController.DataSupplier;
import com.android.documentsui.testing.TestLoaderManager;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -46,7 +46,7 @@
private Context mContext;
private TestLoaderManager mLoaderManager;
- private Loader mLoader;
+ private DataSupplier mLoader;
private ContentResolver mResolver;
@Before
@@ -55,7 +55,7 @@
mContext = InstrumentationRegistry.getTargetContext();
mResolver = mContext.getContentResolver();
mLoaderManager = new TestLoaderManager();
- mLoader = new DocumentLoader(mContext, mLoaderManager);
+ mLoader = new RuntimeDataSupplier(mContext, mLoaderManager);
if (Looper.myLooper() == null) {
Looper.prepare();
diff --git a/tests/unit/com/android/documentsui/inspector/GpsCoordinatesTextClassifierTest.java b/tests/unit/com/android/documentsui/inspector/GpsCoordinatesTextClassifierTest.java
new file mode 100644
index 0000000..8610ea7
--- /dev/null
+++ b/tests/unit/com/android/documentsui/inspector/GpsCoordinatesTextClassifierTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.content.pm.PackageManager;
+import android.os.LocaleList;
+import android.support.test.InstrumentationRegistry;
+
+import android.content.Context;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationManager;
+import android.view.textclassifier.TextClassifier;
+import com.android.documentsui.testing.TestPackageManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for testing recognizing geo coordinates.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class GpsCoordinatesTextClassifierTest {
+
+ private GpsCoordinatesTextClassifier mClassifier;
+
+ @Before
+ public void setUp() throws Exception {
+ PackageManager pm = TestPackageManager.create();
+ Context context = InstrumentationRegistry.getTargetContext();
+
+ TextClassifier defaultClassifier =
+ context.getSystemService(TextClassificationManager.class).getTextClassifier();
+ mClassifier = new GpsCoordinatesTextClassifier(pm, defaultClassifier);
+ }
+
+ @Test
+ public void testBasicPatterns() throws Exception {
+ assertClassifiedGeo("0,0", true);
+ assertClassifiedGeo("0, 0", true);
+ assertClassifiedGeo("0.0,0.0", true);
+ assertClassifiedGeo("0.0, 0.0", true);
+ assertClassifiedGeo("90,180", true);
+ assertClassifiedGeo("90, 180", true);
+ assertClassifiedGeo("90.0000,180.0000", true);
+ assertClassifiedGeo("90.000, 180.000000000000000", true);
+ assertClassifiedGeo("-77.5646564,133.656554654", true);
+ assertClassifiedGeo("33, -179.324234242423", true);
+ assertClassifiedGeo("44.4545454,70.0", true);
+ assertClassifiedGeo("60.0, 60.0", true);
+ assertClassifiedGeo("-33.33,-180", true);
+ assertClassifiedGeo("-88.888888, -33.3333", true);
+ assertClassifiedGeo("90.0, 180.000000", true);
+ assertClassifiedGeo("-90.00000, -180.0", true);
+ }
+
+ @Test
+ public void testInvalidPatterns() throws Exception {
+ assertClassifiedGeo("0", false);
+ assertClassifiedGeo("Geo Intent", false);
+ assertClassifiedGeo("GeoIntent", false);
+ assertClassifiedGeo("A.B, C.D", false);
+ assertClassifiedGeo("90.165464, 180.1", false);
+ // TODO: Failing tests below
+ // assertClassifiedGeo("-90.1, -180.156754", false);
+ // assertClassifiedGeo("5000, 5000", false);
+ // assertClassifiedGeo("500, 500", false);
+ }
+
+ private void assertClassifiedGeo(CharSequence text, boolean expectClassified) {
+ boolean wasClassified;
+ TextClassification test = mClassifier.classifyText(
+ text,
+ 0,
+ text.length(),
+ new LocaleList());
+ try {
+ wasClassified = "geo".equals(test.getIntent().getData().getScheme());
+ } catch (NullPointerException intentNotSet) {
+ wasClassified = false;
+ }
+ assertEquals(wasClassified, expectClassified);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/inspector/HeaderTextSelectorTest.java b/tests/unit/com/android/documentsui/inspector/HeaderTextSelectorTest.java
new file mode 100644
index 0000000..58b533b
--- /dev/null
+++ b/tests/unit/com/android/documentsui/inspector/HeaderTextSelectorTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.widget.TextView;
+import com.android.documentsui.inspector.HeaderTextSelector.Selector;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class HeaderTextSelectorTest {
+
+ private Context mContext;
+ private TestTextView mTestTextView;
+ private TestSelector mTestSelector;
+ private HeaderTextSelector mSelector;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mTestTextView = new TestTextView(mContext);
+ mTestSelector = new TestSelector();
+ mSelector = new HeaderTextSelector(mTestTextView, mTestSelector);
+ }
+
+ @Test
+ public void testSimpleFileName() throws Exception {
+ CharSequence fileName = "filename";
+ String extension = ".txt";
+ String testSequence = fileName + extension;
+
+ mTestTextView.setText(testSequence);
+ mSelector.onCreateActionMode(null, null);
+ mTestSelector.assertCalled();
+
+ CharSequence selectedSequence =
+ testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop);
+ assertEquals(selectedSequence, fileName);
+ }
+
+
+ @Test
+ public void testLotsOfPeriodsInFileName() throws Exception {
+ CharSequence fileName = "filename";
+ String extension = ".jpg.zip.pdf.txt";
+ String testSequence = fileName + extension;
+
+ mTestTextView.setText(testSequence);
+ mSelector.onCreateActionMode(null, null);
+ mTestSelector.assertCalled();
+
+ CharSequence selectedSequence =
+ testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop);
+ assertEquals(selectedSequence, fileName);
+ }
+
+ @Test
+ public void testNoPeriodsInFileName() throws Exception {
+ String testSequence = "filename";
+
+ mTestTextView.setText(testSequence);
+ mSelector.onCreateActionMode(null, null);
+ mTestSelector.assertCalled();
+
+ CharSequence selectedSequence =
+ testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop);
+ assertEquals(selectedSequence, testSequence);
+ }
+
+ private static class TestTextView extends TextView {
+
+ public TestTextView(Context context) {
+ super(context);
+ }
+
+ private String textViewString;
+
+ public void setText(String text) {
+ textViewString = text;
+ }
+
+ @Override
+ public CharSequence getText() {
+ return new SpannableString(textViewString);
+ }
+ }
+
+ private static class TestSelector implements Selector {
+
+ private boolean mCalled;
+ private int mStart;
+ private int mStop;
+
+ public TestSelector() {
+ mCalled = false;
+ mStart = -1;
+ mStop = -1;
+ }
+
+ @Override
+ public void select(Spannable text, int start, int stop) {
+ mCalled = true;
+ mStart = start;
+ mStop = stop;
+ }
+
+ public void assertCalled() {
+ assertTrue(mCalled);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java b/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java
index 68520ef..8f70477 100644
--- a/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java
+++ b/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java
@@ -15,102 +15,116 @@
*/
package com.android.documentsui.inspector;
-import static android.provider.DocumentsContract.Document.FLAG_SUPPORTS_SETTINGS;
+import static junit.framework.Assert.fail;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Looper;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
-import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.View.OnClickListener;
+
import com.android.documentsui.InspectorProvider;
-import com.android.documentsui.ProviderExecutor;
+import com.android.documentsui.R;
+import com.android.documentsui.TestProviderActivity;
import com.android.documentsui.base.DocumentInfo;
-import com.android.documentsui.inspector.InspectorController.DetailsDisplay;
-import com.android.documentsui.inspector.InspectorController.Loader;
-import com.android.documentsui.inspector.actions.Action;
+import com.android.documentsui.base.Shared;
import com.android.documentsui.inspector.InspectorController.ActionDisplay;
+import com.android.documentsui.inspector.InspectorController.DataSupplier;
+import com.android.documentsui.inspector.InspectorController.DebugDisplay;
+import com.android.documentsui.inspector.InspectorController.DetailsDisplay;
+import com.android.documentsui.inspector.InspectorController.HeaderDisplay;
+import com.android.documentsui.inspector.InspectorController.MediaDisplay;
+import com.android.documentsui.inspector.actions.Action;
import com.android.documentsui.testing.TestConsumer;
import com.android.documentsui.testing.TestEnv;
import com.android.documentsui.testing.TestLoaderManager;
import com.android.documentsui.testing.TestPackageManager;
import com.android.documentsui.testing.TestPackageManager.TestResolveInfo;
import com.android.documentsui.testing.TestProvidersAccess;
-import java.util.ArrayList;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class InspectorControllerTest {
private static final String OPEN_IN_PROVIDER_DOC = "OpenInProviderTest";
- private TestActivity mContext;
+ private TestActivity mActivity;
private TestLoaderManager mLoaderManager;
- private Loader mLoader;
+ private TestDataSupplier mDataSupplier;
private TestPackageManager mPm;
private InspectorController mController;
private TestEnv mEnv;
- private TestConsumer<DocumentInfo> mHeaderTestDouble;
+ private TestHeader mHeaderTestDouble;
private TestDetails mDetailsTestDouble;
+ private TestMedia mMedia;
private TestAction mShowInProvider;
private TestAction mDefaultsTestDouble;
- private TestConsumer<DocumentInfo> mDebugTestDouble;
- private Boolean mShowSnackbarsCalled;
+ private TestDebug mDebugTestDouble;
+ private TestRunnable mErrCallback;
+ private Bundle mTestArgs;
@Before
public void setUp() throws Exception {
- //Needed to create a non null loader for the InspectorController.
- Context loader = InstrumentationRegistry.getTargetContext();
mEnv = TestEnv.create();
mPm = TestPackageManager.create();
mLoaderManager = new TestLoaderManager();
- mLoader = new DocumentLoader(loader, mLoaderManager);
- mHeaderTestDouble = new TestConsumer<>();
+ mDataSupplier = new TestDataSupplier();
+ mHeaderTestDouble = new TestHeader();
mDetailsTestDouble = new TestDetails();
+ mMedia = new TestMedia();
mShowInProvider = new TestAction();
mDefaultsTestDouble = new TestAction();
- mDebugTestDouble = new TestConsumer<>();
+ mDebugTestDouble = new TestDebug();
+ mErrCallback = new TestRunnable();
+ mTestArgs = new Bundle();
- mShowSnackbarsCalled = false;
+ // Add some fake data.
+ mDataSupplier.mDoc = TestEnv.FILE_JPG;
+ mDataSupplier.mMetadata = new Bundle();
+ TestMetadata.populateExifData(mDataSupplier.mMetadata);
- //Crashes if not called before "new TestActivity".
+ // Crashes if not called before "new TestActivity".
if (Looper.myLooper() == null) {
Looper.prepare();
}
- mContext = new TestActivity();
+ mActivity = new TestActivity();
+ recreateController();
+ }
+ private void recreateController() {
mController = new InspectorController(
- mContext,
- mLoader,
+ mActivity,
+ mDataSupplier,
mPm,
new TestProvidersAccess(),
- false,
mHeaderTestDouble,
mDetailsTestDouble,
+ mMedia,
mShowInProvider,
mDefaultsTestDouble,
mDebugTestDouble,
- ProviderExecutor::forAuthority,
- () -> {
- mShowSnackbarsCalled = true;
- }
- );
+ mTestArgs,
+ mErrCallback);
}
/**
@@ -118,8 +132,9 @@
*/
@Test
public void testHideDebugByDefault() throws Exception {
- mController.updateView(new DocumentInfo());
- mDebugTestDouble.assertNotCalled();
+ mController.loadInfo(TestEnv.FILE_JPG.derivedUri); // actual URI doesn't matter :)
+ mDebugTestDouble.assertVisible(false);
+ mDebugTestDouble.assertEmpty();
}
/**
@@ -127,25 +142,22 @@
*/
@Test
public void testShowDebugUpdatesView() throws Exception {
- mController = new InspectorController(
- mContext,
- mLoader,
- mPm,
- new TestProvidersAccess(),
- true,
- mHeaderTestDouble,
- mDetailsTestDouble,
- mShowInProvider,
- mDefaultsTestDouble,
- mDebugTestDouble,
- ProviderExecutor::forAuthority,
- () -> {
- mShowSnackbarsCalled = true;
- }
- );
+ mTestArgs.putBoolean(Shared.EXTRA_SHOW_DEBUG, true);
+ recreateController();
+ mController.loadInfo(TestEnv.FILE_JPG.derivedUri); // actual URI doesn't matter :)
+ mDebugTestDouble.assertVisible(true);
+ mDebugTestDouble.assertNotEmpty();
+ }
- mController.updateView(new DocumentInfo());
- mDebugTestDouble.assertCalled();
+ /**
+ * Tests Debug view should be updated when visible.
+ */
+ @Test
+ public void testExtraTitleOverridesDisplayName() throws Exception {
+ mTestArgs.putString(Intent.EXTRA_TITLE, "hammy!");
+ recreateController();
+ mController.loadInfo(TestEnv.FILE_JPG.derivedUri); // actual URI doesn't matter :)
+ mHeaderTestDouble.assertTitle("hammy!");
}
/**
@@ -165,9 +177,9 @@
OPEN_IN_PROVIDER_DOC);
mController.showInProvider(uri);
- assertNotNull(mContext.started);
- assertEquals("com.android.documentsui", mContext.started.getPackage());
- assertEquals(uri, mContext.started.getData());
+ assertNotNull(mActivity.started);
+ assertEquals("com.android.documentsui", mActivity.started.getPackage());
+ assertEquals(uri, mActivity.started.getData());
}
/**
* Test that valid input will update the view properly. The test uses a test double for header
@@ -177,7 +189,7 @@
*/
@Test
public void testUpdateViewWithValidInput() throws Exception {
- mController.updateView(new DocumentInfo());
+ mController.loadInfo(TestEnv.FILE_JPG.derivedUri); // actual URI doesn't matter :)
mHeaderTestDouble.assertCalled();
mDetailsTestDouble.assertCalled();
}
@@ -193,9 +205,9 @@
DocumentInfo doc = new DocumentInfo();
doc.derivedUri =
DocumentsContract.buildDocumentUri(InspectorProvider.AUTHORITY, OPEN_IN_PROVIDER_DOC);
-
doc.flags = doc.flags | Document.FLAG_SUPPORTS_SETTINGS;
- mController.updateView(doc);
+ mDataSupplier.mDoc = doc;
+ mController.loadInfo(doc.derivedUri); // actual URI doesn't matter :)
assertTrue(mShowInProvider.becameVisible);
}
@@ -206,11 +218,7 @@
*/
@Test
public void testShowInProvider_invisible() throws Exception {
- DocumentInfo doc = new DocumentInfo();
- doc.derivedUri =
- DocumentsContract.buildDocumentUri(InspectorProvider.AUTHORITY, OPEN_IN_PROVIDER_DOC);
-
- mController.updateView(doc);
+ mController.loadInfo(TestEnv.FILE_JPG.derivedUri); // actual URI doesn't matter :)
assertFalse(mShowInProvider.becameVisible);
}
@@ -220,7 +228,6 @@
*/
@Test
public void testAppDefaults_visible() throws Exception {
-
mPm.queryIntentProvidersResults = new ArrayList<>();
mPm.queryIntentProvidersResults.add(new TestResolveInfo());
mPm.queryIntentProvidersResults.add(new TestResolveInfo());
@@ -228,7 +235,8 @@
doc.derivedUri =
DocumentsContract.buildDocumentUri(InspectorProvider.AUTHORITY, OPEN_IN_PROVIDER_DOC);
- mController.updateView(doc);
+ mDataSupplier.mDoc = doc;
+ mController.loadInfo(doc.derivedUri); // actual URI doesn't matter :)
assertTrue(mDefaultsTestDouble.becameVisible);
}
@@ -244,7 +252,8 @@
doc.derivedUri =
DocumentsContract.buildDocumentUri(InspectorProvider.AUTHORITY, OPEN_IN_PROVIDER_DOC);
- mController.updateView(doc);
+ mDataSupplier.mDoc = doc;
+ mController.loadInfo(doc.derivedUri); // actual URI doesn't matter :)
assertFalse(mDefaultsTestDouble.becameVisible);
}
@@ -255,13 +264,60 @@
* @throws Exception
*/
@Test
- public void testUpdateViewWithNullValue() throws Exception {
- mController.updateView(null);
- assertTrue(mShowSnackbarsCalled);
+ public void testUpdateView_withNullValue() throws Exception {
+ mDataSupplier.mDoc = null;
+ mController.loadInfo(TestEnv.FILE_JPG.derivedUri); // actual URI doesn't matter :)
+
+ mErrCallback.assertCalled();
mHeaderTestDouble.assertNotCalled();
mDetailsTestDouble.assertNotCalled();
}
+ @Test
+ public void testMetadata_GeoHandlerInstalled() {
+ DocumentInfo doc = TestEnv.clone(TestEnv.FILE_JPG);
+ doc.flags |= DocumentsContract.Document.FLAG_SUPPORTS_METADATA;
+ mDataSupplier.mDoc = doc;
+ mController.loadInfo(doc.derivedUri); // actual URI doesn't matter :)
+ mMedia.assertGeoCallbackInstalled();
+ }
+
+ @Test
+ public void testMetadata_notDisplayedWhenNotReturned() {
+ DocumentInfo doc = TestEnv.clone(TestEnv.FILE_JPG);
+ doc.flags |= DocumentsContract.Document.FLAG_SUPPORTS_METADATA;
+ mDataSupplier.mDoc = doc;
+ mDataSupplier.mMetadata = null; // sorry, no results sucka!
+ mController.loadInfo(doc.derivedUri); // actual URI doesn't matter :)
+ }
+
+ @Test
+ public void testMetadata_notDisplayedDocWithoutSupportFlag() {
+ assert !TestEnv.FILE_JPG.isMetadataSupported();
+ mDataSupplier.mDoc = TestEnv.FILE_JPG; // this is the default value. For "good measure".
+ mController.loadInfo(TestEnv.FILE_JPG.derivedUri); // actual URI doesn't matter :)
+ mMedia.assertVisible(false);
+ mMedia.assertEmpty();
+ }
+
+ @Test
+ public void testMetadata_GeoHandlerStartsAction() {
+ DocumentInfo doc = TestEnv.clone(TestEnv.FILE_JPG);
+ doc.flags |= DocumentsContract.Document.FLAG_SUPPORTS_METADATA;
+ mDataSupplier.mDoc = doc;
+ mController.loadInfo(doc.derivedUri); // actual URI doesn't matter :)
+ mMedia.mGeoClickCallback.run();
+ Intent geoIntent = mActivity.started;
+ assertEquals(Intent.ACTION_VIEW, geoIntent.getAction());
+ assertNotNull(geoIntent);
+ Uri uri = geoIntent.getData();
+ assertEquals("geo", uri.getScheme());
+ String strUri = uri.toSafeString();
+ assertTrue(strUri.contains("33."));
+ assertTrue(strUri.contains("-118."));
+ assertTrue(strUri.contains(TestEnv.FILE_JPG.displayName));
+ }
+
private static class TestActivity extends Activity {
private @Nullable Intent started;
@@ -311,6 +367,31 @@
}
}
+
+ private static class TestHeader implements HeaderDisplay {
+
+ private boolean mCalled = false;
+ private @Nullable String mTitle;
+
+ @Override
+ public void accept(DocumentInfo info, String displayName) {
+ mCalled = true;
+ mTitle = displayName;
+ }
+
+ public void assertTitle(String expected) {
+ Assert.assertEquals(expected, mTitle);
+ }
+
+ public void assertCalled() {
+ Assert.assertTrue(mCalled);
+ }
+
+ public void assertNotCalled() {
+ Assert.assertFalse(mCalled);
+ }
+ }
+
private static class TestDetails implements DetailsDisplay {
private boolean mCalled = false;
@@ -332,4 +413,71 @@
Assert.assertFalse(mCalled);
}
}
+
+ private static class TestMedia extends TestTable implements MediaDisplay {
+
+ private @Nullable Runnable mGeoClickCallback;
+
+ @Override
+ public void accept(DocumentInfo info, Bundle metadata, Runnable geoClickCallback) {
+ mGeoClickCallback = geoClickCallback;
+ }
+
+ void assertGeoCallbackInstalled() {
+ assertNotNull(mGeoClickCallback);
+ }
+ }
+
+ private static class TestDebug extends TestTable implements DebugDisplay {
+
+ @Override
+ public void accept(DocumentInfo info) {
+ // We have to emulate some of the real DebugView behavior
+ // because the controller makes us visible if we're not-empty.
+ put(R.string.debug_content_uri, info.derivedUri.toString());
+ }
+
+ @Override
+ public void accept(Bundle metadata) {
+ }
+ }
+
+ private static final class TestDataSupplier implements DataSupplier {
+
+ private @Nullable DocumentInfo mDoc;
+ private @Nullable Bundle mMetadata;
+
+ @Override
+ public void loadDocInfo(Uri uri, Consumer<DocumentInfo> callback) {
+ callback.accept(mDoc);
+ }
+
+ @Override
+ public void getDocumentMetadata(Uri uri, Consumer<Bundle> callback) {
+ callback.accept(mMetadata);
+ }
+
+ @Override
+ public void loadDirCount(DocumentInfo directory, Consumer<Integer> callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void reset() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static final class TestRunnable implements Runnable {
+ private boolean mCalled;
+
+ @Override
+ public void run() {
+ mCalled = true;
+ }
+
+ void assertCalled() {
+ assertTrue(mCalled);
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/unit/com/android/documentsui/inspector/MediaViewTest.java b/tests/unit/com/android/documentsui/inspector/MediaViewTest.java
new file mode 100644
index 0000000..7cf7b21
--- /dev/null
+++ b/tests/unit/com/android/documentsui/inspector/MediaViewTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import android.media.ExifInterface;
+import android.media.MediaMetadata;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.documentsui.R;
+import com.android.documentsui.base.Shared;
+import com.android.documentsui.testing.TestEnv;
+import com.android.documentsui.testing.TestResources;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MediaViewTest {
+
+ private TestResources mResources;
+ private TestTable mTable;
+ private Bundle mMetadata;
+ private Consumer<float[]> mGeo = (float[] coords) -> {
+ mTable.put(R.string.metadata_address, "1234 Street Street\n"
+ + "City, State, 56789");
+ };
+
+ @Before
+ public void setUp() {
+ mResources = TestResources.create();
+ // TODO: We should just be using the real underlying resources.
+ mResources.strings.put(R.string.metadata_dimensions_format, "%d x %d, %.1fMP");
+ mResources.strings.put(R.string.metadata_aperture_format, "f/%.1f");
+ mResources.strings.put(R.string.metadata_coordinates_format, "%.3f, %.3f");
+ mResources.strings.put(R.string.metadata_camera_format, "%s %s");
+ mTable = new TestTable();
+ mMetadata = new Bundle();
+ TestMetadata.populateExifData(mMetadata);
+ TestMetadata.populateVideoData(mMetadata);
+ TestMetadata.populateAudioData(mMetadata);
+ }
+
+ /**
+ * Test that the updateMetadata method is printing metadata for selected items found in the
+ * bundle.
+ */
+ @Test
+ public void testShowExifData() throws Exception {
+ mResources.strings.put(R.string.metadata_focal_format, "%.2f mm");
+ mResources.strings.put(R.string.metadata_iso_format, "ISO %d");
+ Bundle exif = mMetadata.getBundle(DocumentsContract.METADATA_EXIF);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, exif, null, mGeo);
+
+ mTable.assertHasRow(R.string.metadata_dimensions, "3840 x 2160, 8.3MP");
+ mTable.assertHasRow(R.string.metadata_date_time, "Jan 01, 1970, 12:16 AM");
+ mTable.assertHasRow(R.string.metadata_coordinates, "33.996, -118.475");
+ mTable.assertHasRow(R.string.metadata_altitude, "1244.0");
+ mTable.assertHasRow(R.string.metadata_camera, "Google Pixel");
+ mTable.assertHasRow(R.string.metadata_shutter_speed, "1/100");
+ mTable.assertHasRow(R.string.metadata_aperture, "f/2.0");
+ mTable.assertHasRow(R.string.metadata_iso_speed_ratings, "ISO 120");
+ mTable.assertHasRow(R.string.metadata_focal_length, "4.27 mm");
+ mTable.assertHasRow(R.string.metadata_address, "1234 Street Street\n"
+ + "City, State, 56789");
+ }
+
+ /**
+ * Bundle only supplies half of the values for the pairs that print in printMetaData. No put
+ * method should be called as the correct conditions have not been met.
+ * @throws Exception
+ */
+ @Test
+ public void testShowExifData_PartialGpsTags() throws Exception {
+ Bundle data = new Bundle();
+ data.putDouble(ExifInterface.TAG_GPS_LATITUDE, 37.7749);
+
+ mMetadata.putBundle(DocumentsContract.METADATA_EXIF, data);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null, mGeo);
+ mTable.assertEmpty();
+ }
+
+ /**
+ * Bundle only supplies half of the values for the pairs that print in printMetaData. No put
+ * method should be called as the correct conditions have not been met.
+ * @throws Exception
+ */
+ @Test
+ public void testShowExifData_PartialDimensionTags() throws Exception {
+ Bundle data = new Bundle();
+ data.putInt(ExifInterface.TAG_IMAGE_WIDTH, 3840);
+
+ mMetadata.putBundle(DocumentsContract.METADATA_EXIF, data);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null, mGeo);
+ mTable.assertEmpty();
+ }
+
+ /**
+ * Test that the updateMetadata method is printing metadata for selected items found in the
+ * bundle.
+ */
+ @Test
+ public void testShowVideoData() throws Exception {
+ Bundle data = mMetadata.getBundle(Shared.METADATA_KEY_VIDEO);
+ MediaView.showVideoData(mTable, mResources, TestEnv.FILE_MP4, data, null);
+
+ mTable.assertHasRow(R.string.metadata_duration, "01:12");
+ mTable.assertHasRow(R.string.metadata_dimensions, "1920 x 1080, 2.1MP");
+ }
+
+ @Test
+ public void testShowAudioData() throws Exception {
+ Bundle data = mMetadata.getBundle(Shared.METADATA_KEY_AUDIO);
+ MediaView.showAudioData(mTable, data);
+
+ mTable.assertHasRow(R.string.metadata_duration, "01:12");
+ mTable.assertHasRow(R.string.metadata_artist, "artist");
+ mTable.assertHasRow(R.string.metadata_composer, "composer");
+ mTable.assertHasRow(R.string.metadata_album, "album");
+ }
+
+ /**
+ * Test that the updateMetadata method is printing metadata for selected items found in the
+ * bundle.
+ */
+ @Test
+ public void testShowVideoData_HourPlusDuration() throws Exception {
+ Bundle data = mMetadata.getBundle(Shared.METADATA_KEY_VIDEO);
+ data.putInt(MediaMetadata.METADATA_KEY_DURATION, 21660000);
+ MediaView.showVideoData(mTable, mResources, TestEnv.FILE_MP4, data, null);
+
+ mTable.assertHasRow(R.string.metadata_duration, "6:01:00");
+ }
+
+ @Test
+ public void testGetAddress() throws Exception {
+ Consumer<float[]> badAddress = (float[] coords) -> {
+ };
+ Bundle data = new Bundle();
+ data.putInt(ExifInterface.TAG_IMAGE_WIDTH, 3840);
+ data.putInt(ExifInterface.TAG_IMAGE_LENGTH, 2160);
+
+ mMetadata.getBundle(DocumentsContract.METADATA_EXIF);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null, badAddress);
+ mTable.assertNotInTable(R.string.metadata_address);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/inspector/TestMetadata.java b/tests/unit/com/android/documentsui/inspector/TestMetadata.java
new file mode 100644
index 0000000..a6801ad
--- /dev/null
+++ b/tests/unit/com/android/documentsui/inspector/TestMetadata.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import android.media.ExifInterface;
+import android.media.MediaMetadata;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+
+import com.android.documentsui.base.Shared;
+
+final class TestMetadata {
+ private TestMetadata() {}
+
+ static void populateExifData(Bundle container) {
+ Bundle data = new Bundle();
+ container.putBundle(DocumentsContract.METADATA_EXIF, data);
+
+ data.putInt(ExifInterface.TAG_IMAGE_WIDTH, 3840);
+ data.putInt(ExifInterface.TAG_IMAGE_LENGTH, 2160);
+ data.putString(ExifInterface.TAG_DATETIME, "Jan 01, 1970, 12:16 AM");
+ data.putString(ExifInterface.TAG_GPS_LATITUDE, "33/1,59/1,4530/100");
+ data.putString(ExifInterface.TAG_GPS_LONGITUDE, "118/1,28/1,3124/100");
+ data.putString(ExifInterface.TAG_GPS_LATITUDE_REF, "N");
+ data.putString(ExifInterface.TAG_GPS_LONGITUDE_REF, "W");
+ data.putDouble(ExifInterface.TAG_GPS_ALTITUDE, 1244);
+ data.putString(ExifInterface.TAG_MAKE, "Google");
+ data.putString(ExifInterface.TAG_MODEL, "Pixel");
+ data.putDouble(ExifInterface.TAG_SHUTTER_SPEED_VALUE, 6.643);
+ data.putDouble(ExifInterface.TAG_APERTURE, 2.0);
+ data.putInt(ExifInterface.TAG_ISO_SPEED_RATINGS, 120);
+ data.putDouble(ExifInterface.TAG_FOCAL_LENGTH, 4.27);
+ }
+
+ static void populateVideoData(Bundle container) {
+ Bundle data = new Bundle();
+ container.putBundle(Shared.METADATA_KEY_VIDEO, data);
+
+ // By convention we reuse exif tags for dimensions.
+ data.putInt(ExifInterface.TAG_IMAGE_WIDTH, 1920);
+ data.putInt(ExifInterface.TAG_IMAGE_LENGTH, 1080);
+ data.putInt(MediaMetadata.METADATA_KEY_DURATION, 72000);
+ }
+
+ static void populateAudioData(Bundle container) {
+ Bundle data = new Bundle();
+ container.putBundle(Shared.METADATA_KEY_AUDIO, data);
+
+ data.putInt(MediaMetadata.METADATA_KEY_DURATION, 72000);
+ data.putString(MediaMetadata.METADATA_KEY_ARTIST, "artist");
+ data.putString(MediaMetadata.METADATA_KEY_COMPOSER, "composer");
+ data.putString(MediaMetadata.METADATA_KEY_ALBUM, "album");
+ }
+}
diff --git a/tests/unit/com/android/documentsui/inspector/TestTable.java b/tests/unit/com/android/documentsui/inspector/TestTable.java
new file mode 100644
index 0000000..f1bd0b7
--- /dev/null
+++ b/tests/unit/com/android/documentsui/inspector/TestTable.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.inspector;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import android.view.View.OnClickListener;
+
+import com.android.documentsui.inspector.InspectorController.TableDisplay;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Friendly testable table implementation.
+ */
+class TestTable implements TableDisplay {
+
+ private Map<Integer, CharSequence> mRows;
+ private boolean mVisible;
+
+ public TestTable() {
+ mRows = new HashMap<>();
+ }
+
+ public void assertHasRow(int keyId, CharSequence expected) {
+ assertEquals(expected, mRows.get(keyId));
+ }
+
+ public void assertNotInTable (int keyId) {
+ assertNull(mRows.get(keyId));
+ }
+
+ @Override
+ public void put(int keyId, CharSequence value) {
+ mRows.put(keyId, value);
+ }
+
+ @Override
+ public void put(int keyId, CharSequence value, OnClickListener callback) {
+ mRows.put(keyId, value);
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ mVisible = visible;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mRows.isEmpty();
+ }
+
+ void assertEmpty() {
+ assertTrue(mRows.isEmpty());
+ }
+
+ void assertNotEmpty() {
+ assertFalse(mRows.isEmpty());
+ }
+
+ void assertVisible(boolean expected) {
+ assertEquals(expected, mVisible);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java b/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java
index 8a502bf..5d41565 100644
--- a/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java
+++ b/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java
@@ -80,7 +80,7 @@
mEnv.dialogs.confirmNext();
- mEnv.selectionMgr.toggleSelection("1");
+ mEnv.selectionMgr.select("1");
AsyncTask.setDefaultExecutor(mEnv.mExecutor);
}
diff --git a/tests/unit/com/android/documentsui/prefs/PrefsBackupHelperTest.java b/tests/unit/com/android/documentsui/prefs/PrefsBackupHelperTest.java
index 91ce1ce..3c421c3 100644
--- a/tests/unit/com/android/documentsui/prefs/PrefsBackupHelperTest.java
+++ b/tests/unit/com/android/documentsui/prefs/PrefsBackupHelperTest.java
@@ -27,6 +27,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,9 +55,20 @@
public void setUp() {
mDefaultPrefs = InstrumentationRegistry.getContext().getSharedPreferences("prefs1", 0);
mBackupPrefs = InstrumentationRegistry.getContext().getSharedPreferences("prefs2", 0);
+ clearSharedPrefs();
mPrefsBackupHelper = new PrefsBackupHelper(mDefaultPrefs);
}
+ @After
+ public void tearDown() {
+ clearSharedPrefs();
+ }
+
+ private void clearSharedPrefs() {
+ mDefaultPrefs.edit().clear().commit();
+ mBackupPrefs.edit().clear().commit();
+ }
+
@Test
public void testPrepareBackupFile_BackupLocalPreferences() {
mDefaultPrefs.edit().putInt(LOCAL_PREFERENCE_1, 1).commit();
diff --git a/tests/unit/com/android/documentsui/queries/SearchViewManagerTest.java b/tests/unit/com/android/documentsui/queries/SearchViewManagerTest.java
new file mode 100644
index 0000000..feffaec
--- /dev/null
+++ b/tests/unit/com/android/documentsui/queries/SearchViewManagerTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.queries;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Handler;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.documentsui.R;
+import com.android.documentsui.base.EventHandler;
+import com.android.documentsui.queries.SearchViewManager.SearchManagerListener;
+import com.android.documentsui.queries.SearchViewManager;
+import com.android.documentsui.testing.TestEventHandler;
+import com.android.documentsui.testing.TestHandler;
+import com.android.documentsui.testing.TestMenu;
+import com.android.documentsui.testing.TestTimer;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class SearchViewManagerTest {
+
+ private TestEventHandler<String> mTestEventHandler;
+ private TestTimer mTestTimer;
+ private TestHandler mTestHandler;
+ private SearchViewManager mSearchViewManager;
+
+ private boolean mListenerOnSearchChangedCalled;
+
+ @Before
+ public void setUp() {
+ mTestEventHandler = new TestEventHandler<>();
+ mTestTimer = new TestTimer();
+ mTestHandler = new TestHandler();
+
+ final SearchManagerListener searchListener = new SearchManagerListener() {
+ @Override
+ public void onSearchChanged(@Nullable String query) {
+ mListenerOnSearchChangedCalled = true;
+ }
+ @Override
+ public void onSearchFinished() {}
+ @Override
+ public void onSearchViewChanged(boolean opened) {}
+ };
+
+ mSearchViewManager = new TestableSearchViewManager(
+ searchListener, mTestEventHandler, null, mTestTimer, mTestHandler);
+
+ final TestMenu testMenu = TestMenu.create();
+ mSearchViewManager.install(testMenu, true);
+ }
+
+ private static class TestableSearchViewManager extends SearchViewManager {
+ public TestableSearchViewManager(
+ SearchManagerListener listener,
+ EventHandler<String> commandProcessor,
+ @Nullable Bundle savedState,
+ Timer timer,
+ Handler handler) {
+ super(listener, commandProcessor, savedState, timer, handler);
+ }
+
+ @Override
+ public TimerTask createSearchTask(String newText) {
+ TimerTask task = super.createSearchTask(newText);
+ TestTimer.Task testTask = new TestTimer.Task(task);
+ return testTask;
+ }
+ }
+
+ private void fastForwardTo(long timeMs) {
+ mTestTimer.fastForwardTo(timeMs);
+ mTestHandler.dispatchAllMessages();
+ }
+
+ @Test
+ public void testIsExpanded_ExpandsOnClick() {
+ mSearchViewManager.onClick(null);
+ assertTrue(mSearchViewManager.isExpanded());
+ }
+
+ @Test
+ public void testIsExpanded_CollapsesOnMenuItemActionCollapse() {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onMenuItemActionCollapse(null);
+ assertFalse(mSearchViewManager.isExpanded());
+ }
+
+ @Test
+ public void testIsSearching_FalseOnClick() throws Exception {
+ mSearchViewManager.onClick(null);
+ assertFalse(mSearchViewManager.isSearching());
+ }
+
+ @Test
+ public void testIsSearching_TrueOnQueryTextSubmit() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextSubmit("query");
+ assertTrue(mSearchViewManager.isSearching());
+ }
+
+ @Test
+ public void testIsSearching_FalseImmediatelyAfterOnQueryTextChange() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ assertFalse(mSearchViewManager.isSearching());
+ }
+
+ @Test
+ public void testIsSearching_TrueAfterOnQueryTextChangeAndWait() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS);
+ assertTrue(mSearchViewManager.isSearching());
+ }
+
+ @Test
+ public void testIsSearching_FalseWhenSecondOnQueryTextChangeResetsTimer() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS - 1);
+ mSearchViewManager.onQueryTextChange("qu");
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS);
+ assertFalse(mSearchViewManager.isSearching());
+ }
+
+ @Test
+ public void testIsSearching_TrueAfterSecondOnQueryTextChangeResetsTimer() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS - 1);
+ mSearchViewManager.onQueryTextChange("qu");
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS * 2);
+ assertTrue(mSearchViewManager.isSearching());
+ }
+
+ @Test
+ public void testIsSearching_FalseIfSearchCanceled() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ mSearchViewManager.cancelSearch();
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS);
+ assertFalse(mSearchViewManager.isSearching());
+ }
+
+ @Test
+ public void testOnSearchChanged_CalledAfterOnQueryTextSubmit() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextSubmit("q");
+ assertTrue(mListenerOnSearchChangedCalled);
+ }
+
+ @Test
+ public void testOnSearchChanged_NotCalledImmediatelyAfterOnQueryTextChanged() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ assertFalse(mListenerOnSearchChangedCalled);
+ }
+
+ @Test
+ public void testOnSearchChanged_CalledAfterOnQueryTextChangedAndWait() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS);
+ assertTrue(mListenerOnSearchChangedCalled);
+ }
+
+ @Test
+ public void testOnSearchChanged_CalledOnlyOnceAfterOnQueryTextSubmit() throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ mSearchViewManager.onQueryTextSubmit("q");
+
+ // Clear the flag to check if it gets set again.
+ mListenerOnSearchChangedCalled = false;
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS);
+ assertFalse(mListenerOnSearchChangedCalled);
+ }
+
+ @Test
+ public void testOnSearchChanged_NotCalledForOnQueryTextSubmitIfSearchAlreadyFinished()
+ throws Exception {
+ mSearchViewManager.onClick(null);
+ mSearchViewManager.onQueryTextChange("q");
+ fastForwardTo(SearchViewManager.SEARCH_DELAY_MS);
+ // Clear the flag to check if it gets set again.
+ mListenerOnSearchChangedCalled = false;
+ mSearchViewManager.onQueryTextSubmit("q");
+ assertFalse(mListenerOnSearchChangedCalled);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/BandControllerTest.java b/tests/unit/com/android/documentsui/selection/BandControllerTest.java
deleted file mode 100644
index 6a32147..0000000
--- a/tests/unit/com/android/documentsui/selection/BandControllerTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.support.v7.widget.RecyclerView.OnScrollListener;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.MotionEvent;
-
-import com.android.documentsui.DirectoryReloadLock;
-import com.android.documentsui.dirlist.TestData;
-import com.android.documentsui.dirlist.TestDocumentsAdapter;
-import com.android.documentsui.dirlist.TestFocusHandler;
-import com.android.documentsui.testing.SelectionManagers;
-import com.android.documentsui.testing.TestEvent.Builder;
-
-import java.util.Collections;
-import java.util.List;
-
-@SmallTest
-public class BandControllerTest extends AndroidTestCase {
-
- private static final List<String> ITEMS = TestData.create(10);
- private BandController mBandController;
- private boolean mIsActive;
-
- @Override
- public void setUp() throws Exception {
- mIsActive = false;
- mBandController = new BandController(new TestSelectionEnvironment(),
- new TestDocumentsAdapter(ITEMS), SelectionManagers.createTestInstance(ITEMS),
- new DirectoryReloadLock(), null) {
- @Override
- public boolean isActive() {
- return mIsActive;
- }
- };
- }
-
- public void testGoodStart() {
- assertTrue(mBandController.shouldStart(goodStartEventBuilder().build()));
- }
-
- public void testBadStart_NoButtons() {
- assertFalse(mBandController.shouldStart(
- goodStartEventBuilder().releaseButton(MotionEvent.BUTTON_PRIMARY).build()));
- }
-
- public void testBadStart_SecondaryButton() {
- assertFalse(
- mBandController.shouldStart(goodStartEventBuilder().secondary().build()));
- }
-
- public void testBadStart_TertiaryButton() {
- assertFalse(
- mBandController.shouldStart(goodStartEventBuilder().tertiary().build()));
- }
-
- public void testBadStart_Touch() {
- assertFalse(mBandController.shouldStart(
- goodStartEventBuilder().touch().releaseButton(MotionEvent.BUTTON_PRIMARY).build()));
- }
-
- public void testBadStart_inDragSpot() {
- assertFalse(
- mBandController.shouldStart(goodStartEventBuilder().at(1).inDragHotspot().build()));
- }
-
- public void testBadStart_ActionDown() {
- assertFalse(mBandController
- .shouldStart(goodStartEventBuilder().action(MotionEvent.ACTION_DOWN).build()));
- }
-
- public void testBadStart_ActionUp() {
- assertFalse(mBandController
- .shouldStart(goodStartEventBuilder().action(MotionEvent.ACTION_UP).build()));
- }
-
- public void testBadStart_ActionPointerDown() {
- assertFalse(mBandController.shouldStart(
- goodStartEventBuilder().action(MotionEvent.ACTION_POINTER_DOWN).build()));
- }
-
- public void testBadStart_ActionPointerUp() {
- assertFalse(mBandController.shouldStart(
- goodStartEventBuilder().action(MotionEvent.ACTION_POINTER_UP).build()));
- }
-
- public void testBadStart_NoItems() {
- mBandController = new BandController(new TestSelectionEnvironment(),
- new TestDocumentsAdapter(Collections.EMPTY_LIST),
- SelectionManagers.createTestInstance(ITEMS),
- new DirectoryReloadLock(), null);
- assertFalse(mBandController.shouldStart(goodStartEventBuilder().build()));
- }
-
- public void testBadStart_alreadyActive() {
- mIsActive = true;
- assertFalse(mBandController.shouldStart(goodStartEventBuilder().build()));
- }
-
- public void testGoodStop() {
- mIsActive = true;
- assertTrue(mBandController.shouldStop(goodStopEventBuilder().build()));
- }
-
- public void testGoodStop_PointerUp() {
- mIsActive = true;
- assertTrue(mBandController
- .shouldStop(goodStopEventBuilder().action(MotionEvent.ACTION_POINTER_UP).build()));
- }
-
- public void testGoodStop_Cancel() {
- mIsActive = true;
- assertTrue(mBandController
- .shouldStop(goodStopEventBuilder().action(MotionEvent.ACTION_CANCEL).build()));
- }
-
- public void testBadStop_NotActive() {
- assertFalse(mBandController.shouldStop(goodStopEventBuilder().build()));
- }
-
- public void testBadStop_NonMouse() {
- mIsActive = true;
- assertFalse(mBandController.shouldStop(goodStopEventBuilder().touch().build()));
- }
-
- public void testBadStop_Move() {
- mIsActive = true;
- assertFalse(mBandController.shouldStop(
- goodStopEventBuilder().action(MotionEvent.ACTION_MOVE).touch().build()));
- }
-
- public void testBadStop_Down() {
- mIsActive = true;
- assertFalse(mBandController.shouldStop(
- goodStopEventBuilder().action(MotionEvent.ACTION_DOWN).touch().build()));
- }
-
-
- private Builder goodStartEventBuilder() {
- return new Builder().mouse().primary().action(MotionEvent.ACTION_MOVE).notInDragHotspot();
- }
-
- private Builder goodStopEventBuilder() {
- return new Builder().mouse().action(MotionEvent.ACTION_UP).notInDragHotspot();
- }
-
- private final class TestSelectionEnvironment implements BandController.SelectionEnvironment {
- @Override
- public void scrollBy(int dy) {
- }
-
- @Override
- public void runAtNextFrame(Runnable r) {
- }
-
- @Override
- public void removeCallback(Runnable r) {
- }
-
- @Override
- public void showBand(Rect rect) {
- }
-
- @Override
- public void hideBand() {
- }
-
- @Override
- public void addOnScrollListener(OnScrollListener listener) {
- }
-
- @Override
- public void removeOnScrollListener(OnScrollListener listener) {
- }
-
- @Override
- public int getHeight() {
- return 0;
- }
-
- @Override
- public void invalidateView() {
- }
-
- @Override
- public Point createAbsolutePoint(Point relativePoint) {
- return null;
- }
-
- @Override
- public Rect getAbsoluteRectForChildViewAt(int index) {
- return null;
- }
-
- @Override
- public int getAdapterPositionAt(int index) {
- return 0;
- }
-
- @Override
- public int getColumnCount() {
- return 0;
- }
-
- @Override
- public int getChildCount() {
- return 0;
- }
-
- @Override
- public int getVisibleChildCount() {
- return 0;
- }
-
- @Override
- public boolean hasView(int adapterPosition) {
- return false;
- }
- }
-}
diff --git a/tests/unit/com/android/documentsui/selection/BandSelectionHelperTest.java b/tests/unit/com/android/documentsui/selection/BandSelectionHelperTest.java
new file mode 100644
index 0000000..87b7a1d
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/BandSelectionHelperTest.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.BandSelectionHelper.BandHost;
+import com.android.documentsui.selection.testing.SelectionPredicates;
+import com.android.documentsui.selection.testing.TestAdapter;
+import com.android.documentsui.selection.testing.TestBandPredicate;
+import com.android.documentsui.selection.testing.TestEvents.Builder;
+import com.android.documentsui.selection.testing.TestStableIdProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BandSelectionHelperTest {
+
+ private List<String> mItems;
+ private BandSelectionHelper mBandController;
+ private boolean mIsActive;
+ private Builder mStartBuilder;
+ private Builder mStopBuilder;
+ private MotionEvent mStartEvent;
+ private MotionEvent mStopEvent;
+ private TestBandHost mBandHost;
+ private TestBandPredicate mBandPredicate;
+
+ @Before
+ public void setup() throws Exception {
+ mItems = TestAdapter.createItemList(10);
+ mIsActive = false;
+ TestAdapter adapter = new TestAdapter();
+ adapter.updateTestModelIds(mItems);
+ mBandHost = new TestBandHost();
+ mBandPredicate = new TestBandPredicate();
+
+ SelectionHelper helper = new DefaultSelectionHelper(
+ DefaultSelectionHelper.MODE_SINGLE,
+ adapter,
+ new TestStableIdProvider(adapter),
+ SelectionPredicates.CAN_SET_ANYTHING);
+
+ mBandController = new BandSelectionHelper(
+ mBandHost,
+ adapter,
+ new TestStableIdProvider(adapter),
+ helper,
+ SelectionPredicates.CAN_SET_ANYTHING,
+ mBandPredicate,
+ new ContentLock()) {
+ @Override
+ public boolean isActive() {
+ return mIsActive;
+ }
+ };
+
+ mStartBuilder = new Builder().mouse().primary().action(MotionEvent.ACTION_MOVE);
+ mStopBuilder = new Builder().mouse().action(MotionEvent.ACTION_UP);
+ mStartEvent = mStartBuilder.build();
+ mStopEvent = mStopBuilder.build();
+ }
+
+ @Test
+ public void testGoodStart() {
+ assertTrue(mBandController.shouldStart(mStartEvent));
+ }
+
+ @Test
+ public void testBadStart_NoButtons() {
+ assertFalse(mBandController.shouldStart(
+ mStartBuilder.releaseButton(MotionEvent.BUTTON_PRIMARY).build()));
+ }
+
+ @Test
+ public void testBadStart_SecondaryButton() {
+ assertFalse(
+ mBandController.shouldStart(mStartBuilder.secondary().build()));
+ }
+
+ @Test
+ public void testBadStart_TertiaryButton() {
+ assertFalse(
+ mBandController.shouldStart(mStartBuilder.tertiary().build()));
+ }
+
+ @Test
+ public void testBadStart_Touch() {
+ assertFalse(mBandController.shouldStart(
+ mStartBuilder.touch().releaseButton(MotionEvent.BUTTON_PRIMARY).build()));
+ }
+
+ @Test
+ public void testBadStart_RespectsCanInitiateBand() {
+ mBandPredicate.setCanInitiate(false);
+ assertFalse(mBandController.shouldStart(mStartEvent));
+ }
+
+ @Test
+ public void testBadStart_ActionDown() {
+ assertFalse(mBandController
+ .shouldStart(mStartBuilder.action(MotionEvent.ACTION_DOWN).build()));
+ }
+
+ @Test
+ public void testBadStart_ActionUp() {
+ assertFalse(mBandController
+ .shouldStart(mStartBuilder.action(MotionEvent.ACTION_UP).build()));
+ }
+
+ @Test
+ public void testBadStart_ActionPointerDown() {
+ assertFalse(mBandController.shouldStart(
+ mStartBuilder.action(MotionEvent.ACTION_POINTER_DOWN).build()));
+ }
+
+ @Test
+ public void testBadStart_ActionPointerUp() {
+ assertFalse(mBandController.shouldStart(
+ mStartBuilder.action(MotionEvent.ACTION_POINTER_UP).build()));
+ }
+
+ @Test
+ public void testBadStart_NoItems() {
+ TestAdapter emptyAdapter = new TestAdapter();
+ emptyAdapter.updateTestModelIds(Collections.EMPTY_LIST);
+
+ SelectionHelper helper = new DefaultSelectionHelper(
+ DefaultSelectionHelper.MODE_SINGLE,
+ emptyAdapter,
+ new TestStableIdProvider(emptyAdapter),
+ SelectionPredicates.CAN_SET_ANYTHING);
+
+ mBandController = new BandSelectionHelper(
+ new TestBandHost(),
+ emptyAdapter,
+ new TestStableIdProvider(emptyAdapter),
+ helper,
+ SelectionPredicates.CAN_SET_ANYTHING,
+ mBandPredicate,
+ new ContentLock());
+
+ assertFalse(mBandController.shouldStart(mStartEvent));
+ }
+
+ @Test
+ public void testBadStart_alreadyActive() {
+ mIsActive = true;
+ assertFalse(mBandController.shouldStart(mStartEvent));
+ }
+
+ @Test
+ public void testGoodStop() {
+ mIsActive = true;
+ assertTrue(mBandController.shouldStop(mStopEvent));
+ }
+
+ @Test
+ public void testGoodStop_PointerUp() {
+ mIsActive = true;
+ assertTrue(mBandController
+ .shouldStop(mStopBuilder.action(MotionEvent.ACTION_POINTER_UP).build()));
+ }
+
+ @Test
+ public void testGoodStop_Cancel() {
+ mIsActive = true;
+ assertTrue(mBandController
+ .shouldStop(mStopBuilder.action(MotionEvent.ACTION_CANCEL).build()));
+ }
+
+ @Test
+ public void testBadStop_NotActive() {
+ assertFalse(mBandController.shouldStop(mStopEvent));
+ }
+
+ @Test
+ public void testBadStop_NonMouse() {
+ mIsActive = true;
+ assertFalse(mBandController.shouldStop(mStopBuilder.touch().build()));
+ }
+
+ @Test
+ public void testBadStop_Move() {
+ mIsActive = true;
+ assertFalse(mBandController.shouldStop(
+ mStopBuilder.action(MotionEvent.ACTION_MOVE).touch().build()));
+ }
+
+ @Test
+ public void testBadStop_Down() {
+ mIsActive = true;
+ assertFalse(mBandController.shouldStop(
+ mStopBuilder.action(MotionEvent.ACTION_DOWN).touch().build()));
+ }
+
+ private final class TestBandHost extends BandHost {
+ @Override
+ public void scrollBy(int dy) {
+ }
+
+ @Override
+ public void runAtNextFrame(Runnable r) {
+ }
+
+ @Override
+ public void removeCallback(Runnable r) {
+ }
+
+ @Override
+ public void showBand(Rect rect) {
+ }
+
+ @Override
+ public void hideBand() {
+ }
+
+ @Override
+ public void addOnScrollListener(OnScrollListener listener) {
+ }
+
+ @Override
+ public void removeOnScrollListener(OnScrollListener listener) {
+ }
+
+ @Override
+ public int getHeight() {
+ return 0;
+ }
+
+ @Override
+ public void invalidateView() {
+ }
+
+ @Override
+ public Point createAbsolutePoint(Point relativePoint) {
+ return null;
+ }
+
+ @Override
+ public Rect getAbsoluteRectForChildViewAt(int index) {
+ return null;
+ }
+
+ @Override
+ public int getAdapterPositionAt(int index) {
+ return 0;
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 0;
+ }
+
+ @Override
+ public int getChildCount() {
+ return 0;
+ }
+
+ @Override
+ public int getVisibleChildCount() {
+ return 0;
+ }
+
+ @Override
+ public boolean hasView(int adapterPosition) {
+ return false;
+ }
+ }
+}
diff --git a/tests/unit/com/android/documentsui/DirectoryReloadLockTest.java b/tests/unit/com/android/documentsui/selection/ContentLockTest.java
similarity index 63%
rename from tests/unit/com/android/documentsui/DirectoryReloadLockTest.java
rename to tests/unit/com/android/documentsui/selection/ContentLockTest.java
index dbbc9c6..71b6b0f 100644
--- a/tests/unit/com/android/documentsui/DirectoryReloadLockTest.java
+++ b/tests/unit/com/android/documentsui/selection/ContentLockTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.documentsui;
+package com.android.documentsui.selection;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -28,45 +28,49 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
-public class DirectoryReloadLockTest {
+public class ContentLockTest {
- private DirectoryReloadLock lock = new DirectoryReloadLock();
- private boolean called;
- private Runnable callback = () -> {
- called = true;
+ private ContentLock mLock = new ContentLock();
+ private boolean mCalled;
+
+ private Runnable mRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mCalled = true;
+ }
};
@Before
public void setUp() {
- called = false;
+ mCalled = false;
}
@Test
public void testNotBlocking_callbackNotBlocked() {
- lock.tryUpdate(callback);
- assertTrue(called);
+ mLock.runWhenUnlocked(mRunnable);
+ assertTrue(mCalled);
}
@Test
public void testToggleBlocking_callbackNotBlocked() {
- lock.block();
- lock.unblock();
- lock.tryUpdate(callback);
- assertTrue(called);
+ mLock.block();
+ mLock.unblock();
+ mLock.runWhenUnlocked(mRunnable);
+ assertTrue(mCalled);
}
@Test
public void testBlocking_callbackBlocked() {
- lock.block();
- lock.tryUpdate(callback);
- assertFalse(called);
+ mLock.block();
+ mLock.runWhenUnlocked(mRunnable);
+ assertFalse(mCalled);
}
@Test
public void testBlockthenUnblock_callbackNotBlocked() {
- lock.block();
- lock.tryUpdate(callback);
- lock.unblock();
- assertTrue(called);
+ mLock.block();
+ mLock.runWhenUnlocked(mRunnable);
+ mLock.unblock();
+ assertTrue(mCalled);
}
}
diff --git a/tests/unit/com/android/documentsui/selection/DefaultSelectionHelperTest.java b/tests/unit/com/android/documentsui/selection/DefaultSelectionHelperTest.java
new file mode 100644
index 0000000..48c0b2a
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/DefaultSelectionHelperTest.java
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+import static org.junit.Assert.assertFalse;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseBooleanArray;
+
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+import com.android.documentsui.selection.testing.SelectionProbe;
+import com.android.documentsui.selection.testing.TestAdapter;
+import com.android.documentsui.selection.testing.TestSelectionObserver;
+import com.android.documentsui.selection.testing.TestStableIdProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DefaultSelectionHelperTest {
+
+ private List<String> mItems;
+ private Set<String> mIgnored;
+ private TestAdapter mAdapter;
+ private DefaultSelectionHelper mHelper;
+ private TestSelectionObserver mListener;
+ private SelectionProbe mSelection;
+
+ @Before
+ public void setUp() throws Exception {
+ mIgnored = new HashSet<>();
+ mItems = TestAdapter.createItemList(100);
+ mListener = new TestSelectionObserver();
+ mAdapter = new TestAdapter();
+ mAdapter.updateTestModelIds(mItems);
+
+ SelectionPredicate canSelect = new SelectionPredicate() {
+
+ @Override
+ public boolean canSetStateForId(String id, boolean nextState) {
+ return !nextState || !mIgnored.contains(id);
+ }
+
+ @Override
+ public boolean canSetStateAtPosition(int position, boolean nextState) {
+ throw new UnsupportedOperationException("Not implemented.");
+ }
+ };
+ mHelper = new DefaultSelectionHelper(
+ DefaultSelectionHelper.MODE_MULTIPLE,
+ mAdapter,
+ new TestStableIdProvider(mAdapter),
+ canSelect);
+
+ mHelper.addObserver(mListener);
+
+ mSelection = new SelectionProbe(mHelper, mListener);
+
+ mIgnored.clear();
+ }
+
+ @Test
+ public void testSelect() {
+ mHelper.select(mItems.get(7));
+
+ mSelection.assertSelection(7);
+ }
+
+ @Test
+ public void testDeselect() {
+ mHelper.select(mItems.get(7));
+ mHelper.deselect(mItems.get(7));
+
+ mSelection.assertNoSelection();
+ }
+
+ @Test
+ public void testSelection_DoNothingOnUnselectableItem() {
+ mIgnored.add(mItems.get(7));
+ boolean selected = mHelper.select(mItems.get(7));
+
+ assertFalse(selected);
+ mSelection.assertNoSelection();
+ }
+
+ @Test
+ public void testSelect_NotifiesListenersOfChange() {
+ mHelper.select(mItems.get(7));
+
+ mListener.assertSelectionChanged();
+ }
+
+ @Test
+ public void testSelect_NotifiesAdapterOfSelect() {
+ mHelper.select(mItems.get(7));
+
+ mAdapter.assertNotifiedOfSelectionChange(7);
+ }
+
+ @Test
+ public void testSelect_NotifiesAdapterOfDeselect() {
+ mHelper.select(mItems.get(7));
+ mAdapter.resetSelectionNotifications();
+ mHelper.deselect(mItems.get(7));
+ mAdapter.assertNotifiedOfSelectionChange(7);
+ }
+
+ @Test
+ public void testDeselect_NotifiesSelectionChanged() {
+ mHelper.select(mItems.get(7));
+ mHelper.deselect(mItems.get(7));
+
+ mListener.assertSelectionChanged();
+ }
+
+ @Test
+ public void testSelection_PersistsOnUpdate() {
+ mHelper.select(mItems.get(7));
+ mAdapter.updateTestModelIds(mItems);
+
+ mSelection.assertSelection(7);
+ }
+
+ @Test
+ public void testSelection_IntersectsWithNewDataSet() {
+ mHelper.select(mItems.get(99));
+ mHelper.select(mItems.get(7));
+
+ mAdapter.updateTestModelIds(TestAdapter.createItemList(50));
+
+ mSelection.assertSelection(7);
+ }
+
+ @Test
+ public void testSetItemsSelected() {
+ mHelper.setItemsSelected(getStringIds(6, 7, 8), true);
+
+ mSelection.assertRangeSelected(6, 8);
+ }
+
+ @Test
+ public void testSetItemsSelected_SkipUnselectableItem() {
+ mIgnored.add(mItems.get(7));
+
+ mHelper.setItemsSelected(getStringIds(6, 7, 8), true);
+
+ mSelection.assertSelected(6);
+ mSelection.assertNotSelected(7);
+ mSelection.assertSelected(8);
+ }
+
+ @Test
+ public void testRangeSelection() {
+ mHelper.startRange(15);
+ mHelper.extendRange(19);
+ mSelection.assertRangeSelection(15, 19);
+ }
+
+ @Test
+ public void testRangeSelection_SkipUnselectableItem() {
+ mIgnored.add(mItems.get(17));
+
+ mHelper.startRange(15);
+ mHelper.extendRange(19);
+
+ mSelection.assertRangeSelected(15, 16);
+ mSelection.assertNotSelected(17);
+ mSelection.assertRangeSelected(18, 19);
+ }
+
+ @Test
+ public void testRangeSelection_snapExpand() {
+ mHelper.startRange(15);
+ mHelper.extendRange(19);
+ mHelper.extendRange(27);
+ mSelection.assertRangeSelection(15, 27);
+ }
+
+ @Test
+ public void testRangeSelection_snapContract() {
+ mHelper.startRange(15);
+ mHelper.extendRange(27);
+ mHelper.extendRange(19);
+ mSelection.assertRangeSelection(15, 19);
+ }
+
+ @Test
+ public void testRangeSelection_snapInvert() {
+ mHelper.startRange(15);
+ mHelper.extendRange(27);
+ mHelper.extendRange(3);
+ mSelection.assertRangeSelection(3, 15);
+ }
+
+ @Test
+ public void testRangeSelection_multiple() {
+ mHelper.startRange(15);
+ mHelper.extendRange(27);
+ mHelper.endRange();
+ mHelper.startRange(42);
+ mHelper.extendRange(57);
+ mSelection.assertSelectionSize(29);
+ mSelection.assertRangeSelected(15, 27);
+ mSelection.assertRangeSelected(42, 57);
+ }
+
+ @Test
+ public void testProvisionalRangeSelection() {
+ mHelper.startRange(13);
+ mHelper.extendProvisionalRange(15);
+ mSelection.assertRangeSelection(13, 15);
+ mHelper.getSelection().mergeProvisionalSelection();
+ mHelper.endRange();
+ mSelection.assertSelectionSize(3);
+ }
+
+ @Test
+ public void testProvisionalRangeSelection_endEarly() {
+ mHelper.startRange(13);
+ mHelper.extendProvisionalRange(15);
+ mSelection.assertRangeSelection(13, 15);
+
+ mHelper.endRange();
+ // If we end range selection prematurely for provision selection, nothing should be selected
+ // except the first item
+ mSelection.assertSelectionSize(1);
+ }
+
+ @Test
+ public void testProvisionalRangeSelection_snapExpand() {
+ mHelper.startRange(13);
+ mHelper.extendProvisionalRange(15);
+ mSelection.assertRangeSelection(13, 15);
+ mHelper.getSelection().mergeProvisionalSelection();
+ mHelper.extendRange(18);
+ mSelection.assertRangeSelection(13, 18);
+ }
+
+ @Test
+ public void testCombinationRangeSelection_IntersectsOldSelection() {
+ mHelper.startRange(13);
+ mHelper.extendRange(15);
+ mSelection.assertRangeSelection(13, 15);
+
+ mHelper.startRange(11);
+ mHelper.extendProvisionalRange(18);
+ mSelection.assertRangeSelected(11, 18);
+ mHelper.endRange();
+ mSelection.assertRangeSelected(13, 15);
+ mSelection.assertRangeSelected(11, 11);
+ mSelection.assertSelectionSize(4);
+ }
+
+ @Test
+ public void testProvisionalSelection() {
+ Selection s = mHelper.getSelection();
+ mSelection.assertNoSelection();
+
+ // Mimicking band selection case -- BandController notifies item callback by itself.
+ mListener.onItemStateChanged(mItems.get(1), true);
+ mListener.onItemStateChanged(mItems.get(2), true);
+
+ SparseBooleanArray provisional = new SparseBooleanArray();
+ provisional.append(1, true);
+ provisional.append(2, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+ mSelection.assertSelection(1, 2);
+ }
+
+ @Test
+ public void testProvisionalSelection_Replace() {
+ Selection s = mHelper.getSelection();
+
+ // Mimicking band selection case -- BandController notifies item callback by itself.
+ mListener.onItemStateChanged(mItems.get(1), true);
+ mListener.onItemStateChanged(mItems.get(2), true);
+ SparseBooleanArray provisional = new SparseBooleanArray();
+ provisional.append(1, true);
+ provisional.append(2, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+
+ mListener.onItemStateChanged(mItems.get(1), false);
+ mListener.onItemStateChanged(mItems.get(2), false);
+ provisional.clear();
+
+ mListener.onItemStateChanged(mItems.get(3), true);
+ mListener.onItemStateChanged(mItems.get(4), true);
+ provisional.append(3, true);
+ provisional.append(4, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+ mSelection.assertSelection(3, 4);
+ }
+
+ @Test
+ public void testProvisionalSelection_IntersectsExistingProvisionalSelection() {
+ Selection s = mHelper.getSelection();
+
+ // Mimicking band selection case -- BandController notifies item callback by itself.
+ mListener.onItemStateChanged(mItems.get(1), true);
+ mListener.onItemStateChanged(mItems.get(2), true);
+ SparseBooleanArray provisional = new SparseBooleanArray();
+ provisional.append(1, true);
+ provisional.append(2, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+
+ mListener.onItemStateChanged(mItems.get(1), false);
+ mListener.onItemStateChanged(mItems.get(2), false);
+ provisional.clear();
+
+ mListener.onItemStateChanged(mItems.get(1), true);
+ provisional.append(1, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+ mSelection.assertSelection(1);
+ }
+
+ @Test
+ public void testProvisionalSelection_Apply() {
+ Selection s = mHelper.getSelection();
+
+ // Mimicking band selection case -- BandController notifies item callback by itself.
+ mListener.onItemStateChanged(mItems.get(1), true);
+ mListener.onItemStateChanged(mItems.get(2), true);
+ SparseBooleanArray provisional = new SparseBooleanArray();
+ provisional.append(1, true);
+ provisional.append(2, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+ s.mergeProvisionalSelection();
+
+ mSelection.assertSelection(1, 2);
+ }
+
+ @Test
+ public void testProvisionalSelection_Cancel() {
+ mHelper.select(mItems.get(1));
+ mHelper.select(mItems.get(2));
+ Selection s = mHelper.getSelection();
+
+ SparseBooleanArray provisional = new SparseBooleanArray();
+ provisional.append(3, true);
+ provisional.append(4, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+ s.clearProvisionalSelection();
+
+ // Original selection should remain.
+ mSelection.assertSelection(1, 2);
+ }
+
+ @Test
+ public void testProvisionalSelection_IntersectsAppliedSelection() {
+ mHelper.select(mItems.get(1));
+ mHelper.select(mItems.get(2));
+ Selection s = mHelper.getSelection();
+
+ // Mimicking band selection case -- BandController notifies item callback by itself.
+ mListener.onItemStateChanged(mItems.get(3), true);
+ SparseBooleanArray provisional = new SparseBooleanArray();
+ provisional.append(2, true);
+ provisional.append(3, true);
+ s.setProvisionalSelection(getItemIds(provisional));
+ mSelection.assertSelection(1, 2, 3);
+ }
+
+ @Test
+ public void testObserverOnChanged_NotifiesListenersOfChange() {
+ mAdapter.notifyDataSetChanged();
+
+ mListener.assertSelectionChanged();
+ }
+
+ private Set<String> getItemIds(SparseBooleanArray selection) {
+ Set<String> ids = new HashSet<>();
+
+ int count = selection.size();
+ for (int i = 0; i < count; ++i) {
+ ids.add(mItems.get(selection.keyAt(i)));
+ }
+
+ return ids;
+ }
+
+ private Iterable<String> getStringIds(int... ids) {
+ List<String> stringIds = new ArrayList<>(ids.length);
+ for (int id : ids) {
+ stringIds.add(mItems.get(id));
+ }
+ return stringIds;
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/DefaultSelectionHelper_SingleSelectTest.java b/tests/unit/com/android/documentsui/selection/DefaultSelectionHelper_SingleSelectTest.java
new file mode 100644
index 0000000..563ce87
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/DefaultSelectionHelper_SingleSelectTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static org.junit.Assert.fail;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.documentsui.selection.testing.SelectionPredicates;
+import com.android.documentsui.selection.testing.SelectionProbe;
+import com.android.documentsui.selection.testing.TestAdapter;
+import com.android.documentsui.selection.testing.TestSelectionObserver;
+import com.android.documentsui.selection.testing.TestStableIdProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DefaultSelectionHelper_SingleSelectTest {
+
+ private List<String> mItems;
+ private SelectionHelper mHelper;
+ private TestSelectionObserver mListener;
+ private SelectionProbe mSelection;
+
+ @Before
+ public void setUp() throws Exception {
+ mItems = TestAdapter.createItemList(100);
+ mListener = new TestSelectionObserver();
+ TestAdapter adapter = new TestAdapter();
+ adapter.updateTestModelIds(mItems);
+
+ mHelper = new DefaultSelectionHelper(
+ DefaultSelectionHelper.MODE_SINGLE,
+ adapter,
+ new TestStableIdProvider(adapter),
+ SelectionPredicates.CAN_SET_ANYTHING);
+
+ mHelper.addObserver(mListener);
+
+ mSelection = new SelectionProbe(mHelper);
+ }
+
+ @Test
+ public void testSimpleSelect() {
+ mHelper.select(mItems.get(3));
+ mHelper.select(mItems.get(4));
+ mListener.assertSelectionChanged();
+ mSelection.assertSelection(4);
+ }
+
+ @Test
+ public void testRangeSelectionNotEstablished() {
+ mHelper.select(mItems.get(3));
+ mListener.reset();
+
+ try {
+ mHelper.extendRange(10);
+ fail("Should have thrown.");
+ } catch (Exception expected) {}
+
+ mListener.assertSelectionUnchanged();
+ mSelection.assertSelection(3);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/GestureRouterTest.java b/tests/unit/com/android/documentsui/selection/GestureRouterTest.java
new file mode 100644
index 0000000..e467f0f
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/GestureRouterTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyFloat;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.GestureDetector.OnDoubleTapListener;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.testing.TestEvents.Mouse;
+import com.android.documentsui.selection.testing.TestEvents.Touch;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class GestureRouterTest {
+
+ private TestHandler mHandler;
+ private TestHandler mAlt;
+ private GestureRouter<TestHandler> mRouter;
+
+ @Before
+ public void setUp() {
+ mAlt = new TestHandler();
+ mHandler = new TestHandler();
+ }
+
+ @Test
+ public void testDelegates() {
+ mRouter = new GestureRouter<>();
+ mRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mHandler);
+ mRouter.register(MotionEvent.TOOL_TYPE_FINGER, mAlt);
+
+ mRouter.onDown(Mouse.CLICK);
+ mHandler.assertCalled_onDown(Mouse.CLICK);
+ mAlt.assertNotCalled_onDown();
+
+ mRouter.onShowPress(Mouse.CLICK);
+ mHandler.assertCalled_onShowPress(Mouse.CLICK);
+ mAlt.assertNotCalled_onShowPress();
+
+ mRouter.onSingleTapUp(Mouse.CLICK);
+ mHandler.assertCalled_onSingleTapUp(Mouse.CLICK);
+ mAlt.assertNotCalled_onSingleTapUp();
+
+ mRouter.onScroll(null, Mouse.CLICK, -1, -1);
+ mHandler.assertCalled_onScroll(null, Mouse.CLICK, -1, -1);
+ mAlt.assertNotCalled_onScroll();
+
+ mRouter.onLongPress(Mouse.CLICK);
+ mHandler.assertCalled_onLongPress(Mouse.CLICK);
+ mAlt.assertNotCalled_onLongPress();
+
+ mRouter.onFling(null, Mouse.CLICK, -1, -1);
+ mHandler.assertCalled_onFling(null, Mouse.CLICK, -1, -1);
+ mAlt.assertNotCalled_onFling();
+
+ mRouter.onSingleTapConfirmed(Mouse.CLICK);
+ mHandler.assertCalled_onSingleTapConfirmed(Mouse.CLICK);
+ mAlt.assertNotCalled_onSingleTapConfirmed();
+
+ mRouter.onDoubleTap(Mouse.CLICK);
+ mHandler.assertCalled_onDoubleTap(Mouse.CLICK);
+ mAlt.assertNotCalled_onDoubleTap();
+
+ mRouter.onDoubleTapEvent(Mouse.CLICK);
+ mHandler.assertCalled_onDoubleTapEvent(Mouse.CLICK);
+ mAlt.assertNotCalled_onDoubleTapEvent();
+ }
+
+ @Test
+ public void testFallsback() {
+ mRouter = new GestureRouter<>(mAlt);
+ mRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mHandler);
+
+ mRouter.onDown(Touch.TAP);
+ mAlt.assertCalled_onDown(Touch.TAP);
+
+ mRouter.onShowPress(Touch.TAP);
+ mAlt.assertCalled_onShowPress(Touch.TAP);
+
+ mRouter.onSingleTapUp(Touch.TAP);
+ mAlt.assertCalled_onSingleTapUp(Touch.TAP);
+
+ mRouter.onScroll(null, Touch.TAP, -1, -1);
+ mAlt.assertCalled_onScroll(null, Touch.TAP, -1, -1);
+
+ mRouter.onLongPress(Touch.TAP);
+ mAlt.assertCalled_onLongPress(Touch.TAP);
+
+ mRouter.onFling(null, Touch.TAP, -1, -1);
+ mAlt.assertCalled_onFling(null, Touch.TAP, -1, -1);
+
+ mRouter.onSingleTapConfirmed(Touch.TAP);
+ mAlt.assertCalled_onSingleTapConfirmed(Touch.TAP);
+
+ mRouter.onDoubleTap(Touch.TAP);
+ mAlt.assertCalled_onDoubleTap(Touch.TAP);
+
+ mRouter.onDoubleTapEvent(Touch.TAP);
+ mAlt.assertCalled_onDoubleTapEvent(Touch.TAP);
+ }
+
+ @Test
+ public void testEatsEventsWhenNoFallback() {
+ mRouter = new GestureRouter<>();
+ // Register the the delegate on mouse so touch events don't get handled.
+ mRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mHandler);
+
+ mRouter.onDown(Touch.TAP);
+ mAlt.assertNotCalled_onDown();
+
+ mRouter.onShowPress(Touch.TAP);
+ mAlt.assertNotCalled_onShowPress();
+
+ mRouter.onSingleTapUp(Touch.TAP);
+ mAlt.assertNotCalled_onSingleTapUp();
+
+ mRouter.onScroll(null, Touch.TAP, -1, -1);
+ mAlt.assertNotCalled_onScroll();
+
+ mRouter.onLongPress(Touch.TAP);
+ mAlt.assertNotCalled_onLongPress();
+
+ mRouter.onFling(null, Touch.TAP, -1, -1);
+ mAlt.assertNotCalled_onFling();
+
+ mRouter.onSingleTapConfirmed(Touch.TAP);
+ mAlt.assertNotCalled_onSingleTapConfirmed();
+
+ mRouter.onDoubleTap(Touch.TAP);
+ mAlt.assertNotCalled_onDoubleTap();
+
+ mRouter.onDoubleTapEvent(Touch.TAP);
+ mAlt.assertNotCalled_onDoubleTapEvent();
+ }
+
+ private static final class TestHandler implements OnGestureListener, OnDoubleTapListener {
+
+ private final Spy mSpy = Mockito.mock(Spy.class);
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return mSpy.onDown(e);
+ }
+
+ @Override
+ public void onShowPress(MotionEvent e) {
+ mSpy.onShowPress(e);
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ return mSpy.onSingleTapUp(e);
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ return mSpy.onScroll(e1, e2, distanceX, distanceY);
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+ mSpy.onLongPress(e);
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ return mSpy.onFling(e1, e2, velocityX, velocityY);
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ return mSpy.onSingleTapConfirmed(e);
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ return mSpy.onDoubleTap(e);
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent e) {
+ return mSpy.onDoubleTapEvent(e);
+ }
+
+ void assertCalled_onDown(MotionEvent e) {
+ verify(mSpy).onDown(e);
+ }
+
+ void assertCalled_onShowPress(MotionEvent e) {
+ verify(mSpy).onShowPress(e);
+ }
+
+ void assertCalled_onSingleTapUp(MotionEvent e) {
+ verify(mSpy).onSingleTapUp(e);
+ }
+
+ void assertCalled_onScroll(MotionEvent e1, MotionEvent e2, float x, float y) {
+ verify(mSpy).onScroll(e1, e2, x, y);
+ }
+
+ void assertCalled_onLongPress(MotionEvent e) {
+ verify(mSpy).onLongPress(e);
+ }
+
+ void assertCalled_onFling(MotionEvent e1, MotionEvent e2, float x, float y) {
+ Mockito.verify(mSpy).onFling(e1, e2, x, y);
+ }
+
+ void assertCalled_onSingleTapConfirmed(MotionEvent e) {
+ Mockito.verify(mSpy).onSingleTapConfirmed(e);
+ }
+
+ void assertCalled_onDoubleTap(MotionEvent e) {
+ Mockito.verify(mSpy).onDoubleTap(e);
+ }
+
+ void assertCalled_onDoubleTapEvent(MotionEvent e) {
+ Mockito.verify(mSpy).onDoubleTapEvent(e);
+ }
+
+ void assertNotCalled_onDown() {
+ verify(mSpy, never()).onDown(any());
+ }
+
+ void assertNotCalled_onShowPress() {
+ verify(mSpy, never()).onShowPress(any());
+ }
+
+ void assertNotCalled_onSingleTapUp() {
+ verify(mSpy, never()).onSingleTapUp(any());
+ }
+
+ void assertNotCalled_onScroll() {
+ verify(mSpy, never()).onScroll(any(), any(), anyFloat(), anyFloat());
+ }
+
+ void assertNotCalled_onLongPress() {
+ verify(mSpy, never()).onLongPress(any());
+ }
+
+ void assertNotCalled_onFling() {
+ Mockito.verify(mSpy, never()).onFling(any(), any(), anyFloat(), anyFloat());
+ }
+
+ void assertNotCalled_onSingleTapConfirmed() {
+ Mockito.verify(mSpy, never()).onSingleTapConfirmed(any());
+ }
+
+ void assertNotCalled_onDoubleTap() {
+ Mockito.verify(mSpy, never()).onDoubleTap(any());
+ }
+
+ void assertNotCalled_onDoubleTapEvent() {
+ Mockito.verify(mSpy, never()).onDoubleTapEvent(any());
+ }
+ }
+
+ private static interface Spy extends OnGestureListener, OnDoubleTapListener {}
+}
diff --git a/tests/unit/com/android/documentsui/selection/GestureSelectionHelperTest.java b/tests/unit/com/android/documentsui/selection/GestureSelectionHelperTest.java
new file mode 100644
index 0000000..71b1c14
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/GestureSelectionHelperTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.testing.SelectionProbe;
+import com.android.documentsui.selection.testing.TestData;
+import com.android.documentsui.testing.SelectionHelpers;
+import com.android.documentsui.testing.TestEvents;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class GestureSelectionHelperTest {
+
+ private static final List<String> ITEMS = TestData.create(100);
+ private static final MotionEvent DOWN = TestEvents.builder()
+ .action(MotionEvent.ACTION_DOWN)
+ .location(1, 1)
+ .build();
+
+ private static final MotionEvent MOVE = TestEvents.builder()
+ .action(MotionEvent.ACTION_MOVE)
+ .location(1, 1)
+ .build();
+
+ private static final MotionEvent UP = TestEvents.builder()
+ .action(MotionEvent.ACTION_UP)
+ .location(1, 1)
+ .build();
+
+ private GestureSelectionHelper mHelper;
+ private SelectionHelper mSelectionHelper;
+ private SelectionProbe mSelection;
+ private ContentLock mLock;
+ private TestViewDelegate mView;
+
+ @Before
+ public void setUp() {
+ mSelectionHelper = SelectionHelpers.createTestInstance(ITEMS);
+ mSelection = new SelectionProbe(mSelectionHelper);
+ mLock = new ContentLock();
+ mView = new TestViewDelegate();
+ mHelper = new GestureSelectionHelper(mSelectionHelper, mView, mLock);
+ }
+
+ @Test
+ public void testIgnoresDownOnNoPosition() {
+ mView.mNextPosition = RecyclerView.NO_POSITION;
+ assertFalse(mHelper.onInterceptTouchEvent(null, DOWN));
+ }
+
+
+ @Test
+ public void testNoStartOnIllegalPosition() {
+ mHelper.onInterceptTouchEvent(null, DOWN);
+ try {
+ mHelper.start();
+ fail("Should have thrown.");
+ } catch (Exception expected) {}
+ }
+
+ @Test
+ public void testClaimsDownOnItem() {
+ mView.mNextPosition = 0;
+ assertTrue(mHelper.onInterceptTouchEvent(null, DOWN));
+ }
+
+ @Test
+ public void testClaimsMoveIfStarted() {
+ mView.mNextPosition = 0;
+ assertTrue(mHelper.onInterceptTouchEvent(null, DOWN));
+
+ // Normally, this is controller by the TouchSelectionHelper via a a long press gesture.
+ mSelectionHelper.select("1");
+ mSelectionHelper.anchorRange(1);
+ mHelper.start();
+ assertTrue(mHelper.onInterceptTouchEvent(null, MOVE));
+ }
+
+ @Test
+ public void testCreatesRangeSelection() {
+ mView.mNextPosition = 1;
+ mHelper.onInterceptTouchEvent(null, DOWN);
+ // Another way we are implicitly coupled to TouchInputHandler, is that we depend on
+ // long press to establish the initial anchor point. Without that we'll get an
+ // error when we try to extend the range.
+
+ mSelectionHelper.select("1");
+ mSelectionHelper.anchorRange(1);
+ mHelper.start();
+
+ mHelper.onTouchEvent(null, MOVE);
+
+ mView.mNextPosition = 9;
+ mHelper.onTouchEvent(null, MOVE);
+ mHelper.onTouchEvent(null, UP);
+
+ mSelection.assertRangeSelected(1, 9);
+ }
+
+ private static final class TestViewDelegate extends GestureSelectionHelper.ViewDelegate {
+
+ private int mNextPosition = RecyclerView.NO_POSITION;
+
+ @Override
+ int getHeight() {
+ return 1000;
+ }
+
+ @Override
+ int getItemUnder(MotionEvent e) {
+ return mNextPosition;
+ }
+
+ @Override
+ int getLastGlidedItemPosition(MotionEvent e) {
+ return mNextPosition;
+ }
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/GestureSelectionHelper_RecyclerViewDelegateTest.java b/tests/unit/com/android/documentsui/selection/GestureSelectionHelper_RecyclerViewDelegateTest.java
new file mode 100644
index 0000000..9e05d0c
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/GestureSelectionHelper_RecyclerViewDelegateTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.documentsui.selection.GestureSelectionHelper.RecyclerViewDelegate;
+import com.android.documentsui.testing.TestEvents;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class GestureSelectionHelper_RecyclerViewDelegateTest {
+
+ // Simulate a (20, 20) box locating at (20, 20)
+ static final int LEFT_BORDER = 20;
+ static final int RIGHT_BORDER = 40;
+ static final int TOP_BORDER = 20;
+ static final int BOTTOM_BORDER = 40;
+
+ @Test
+ public void testLtrPastLastItem() {
+ MotionEvent event = createEvent(100, 100);
+ assertTrue(RecyclerViewDelegate.isPastLastItem(
+ TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, event, View.LAYOUT_DIRECTION_LTR));
+ }
+
+ @Test
+ public void testLtrPastLastItem_Inverse() {
+ MotionEvent event = createEvent(10, 10);
+ assertFalse(RecyclerViewDelegate.isPastLastItem(
+ TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, event, View.LAYOUT_DIRECTION_LTR));
+ }
+
+ @Test
+ public void testRtlPastLastItem() {
+ MotionEvent event = createEvent(10, 30);
+ assertTrue(RecyclerViewDelegate.isPastLastItem(
+ TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, event, View.LAYOUT_DIRECTION_RTL));
+ }
+
+ @Test
+ public void testRtlPastLastItem_Inverse() {
+ MotionEvent event = createEvent(100, 100);
+ assertFalse(RecyclerViewDelegate.isPastLastItem(
+ TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, event, View.LAYOUT_DIRECTION_RTL));
+ }
+
+ private static MotionEvent createEvent(int x, int y) {
+ return TestEvents.builder().action(MotionEvent.ACTION_MOVE).location(x, y).build();
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/GestureSelectorTest.java b/tests/unit/com/android/documentsui/selection/GestureSelectorTest.java
deleted file mode 100644
index 85a857a..0000000
--- a/tests/unit/com/android/documentsui/selection/GestureSelectorTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.View;
-
-import com.android.documentsui.selection.GestureSelector;
-import com.android.documentsui.testing.TestEvent;
-
-@SmallTest
-public class GestureSelectorTest extends AndroidTestCase {
-
- TestEvent.Builder e;
-
- // Simulate a (20, 20) box locating at (20, 20)
- static final int LEFT_BORDER = 20;
- static final int RIGHT_BORDER = 40;
- static final int TOP_BORDER = 20;
- static final int BOTTOM_BORDER = 40;
-
- @Override
- public void setUp() throws Exception {
- e = TestEvent.builder()
- .location(100, 100);
- }
-
- public void testLTRPastLastItem() {
- assertTrue(GestureSelector.isPastLastItem(
- TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, e.build(), View.LAYOUT_DIRECTION_LTR));
- }
-
- public void testLTRPastLastItem_Inverse() {
- e.location(10, 10);
- assertFalse(GestureSelector.isPastLastItem(
- TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, e.build(), View.LAYOUT_DIRECTION_LTR));
- }
-
- public void testRTLPastLastItem() {
- e.location(10, 30);
- assertTrue(GestureSelector.isPastLastItem(
- TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, e.build(), View.LAYOUT_DIRECTION_RTL));
- }
-
- public void testRTLPastLastItem_Inverse() {
- assertFalse(GestureSelector.isPastLastItem(
- TOP_BORDER, LEFT_BORDER, RIGHT_BORDER, e.build(), View.LAYOUT_DIRECTION_RTL));
- }
-}
diff --git a/tests/unit/com/android/documentsui/selection/BandController_GridModelTest.java b/tests/unit/com/android/documentsui/selection/GridModelTest.java
similarity index 78%
rename from tests/unit/com/android/documentsui/selection/BandController_GridModelTest.java
rename to tests/unit/com/android/documentsui/selection/GridModelTest.java
index 4ce161d..1cb2900 100644
--- a/tests/unit/com/android/documentsui/selection/BandController_GridModelTest.java
+++ b/tests/unit/com/android/documentsui/selection/GridModelTest.java
@@ -16,33 +16,45 @@
package com.android.documentsui.selection;
-import static com.android.documentsui.selection.BandController.GridModel.NOT_SET;
+import static com.android.documentsui.selection.GridModel.NOT_SET;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.graphics.Point;
import android.graphics.Rect;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.support.v7.widget.RecyclerView.OnScrollListener;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import com.android.documentsui.dirlist.TestDocumentsAdapter;
-import com.android.documentsui.selection.BandController.GridModel;
+import com.android.documentsui.selection.BandSelectionHelper.BandHost;
+import com.android.documentsui.selection.testing.SelectionPredicates;
+import com.android.documentsui.selection.testing.TestAdapter;
+import com.android.documentsui.selection.testing.TestStableIdProvider;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import javax.annotation.Nullable;
+
+@RunWith(AndroidJUnit4.class)
@SmallTest
-public class BandController_GridModelTest extends AndroidTestCase {
+public class GridModelTest {
private static final int VIEW_PADDING_PX = 5;
private static final int CHILD_VIEW_EDGE_PX = 100;
private static final int VIEWPORT_HEIGHT = 500;
- private GridModel model;
- private TestEnvironment env;
- private TestDocumentsAdapter adapter;
- private Set<String> lastSelection;
- private int viewWidth;
+ private GridModel mModel;
+ private TestHost mHost;
+ private TestAdapter mAdapter;
+ private Set<String> mLastSelection;
+ private int mViewWidth;
// TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and
// #resizeSelection methods instead.
@@ -55,91 +67,68 @@
private Point mSelectionOrigin;
private Point mSelectionPoint;
- private void initData(final int numChildren, int numColumns) {
- env = new TestEnvironment(numChildren, numColumns);
- adapter = new TestDocumentsAdapter(new ArrayList<String>()) {
- @Override
- public String getModelId(int position) {
- return Integer.toString(position);
- }
-
- @Override
- public int getItemCount() {
- return numChildren;
- }
- };
-
- viewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX);
- model = new GridModel(env, (int pos) -> true, adapter);
- model.addOnSelectionChangedListener(
- new GridModel.OnSelectionChangedListener() {
- @Override
- public void onSelectionChanged(Set<String> updatedSelection) {
- lastSelection = updatedSelection;
- }
-
- @Override
- public boolean onBeforeItemStateChange(String id, boolean nextState) {
- return true;
- }
- });
- }
-
- @Override
+ @After
public void tearDown() {
- model = null;
- env = null;
- lastSelection = null;
+ mModel = null;
+ mHost = null;
+ mLastSelection = null;
}
+ @Test
public void testSelectionLeftOfItems() {
initData(20, 5);
startSelection(new Point(0, 10));
resizeSelection(new Point(1, 11));
assertNoSelection();
- assertEquals(NOT_SET, model.getPositionNearestOrigin());
+ assertEquals(NOT_SET, mModel.getPositionNearestOrigin());
}
+ @Test
public void testSelectionRightOfItems() {
initData(20, 4);
- startSelection(new Point(viewWidth - 1, 10));
- resizeSelection(new Point(viewWidth - 2, 11));
+ startSelection(new Point(mViewWidth - 1, 10));
+ resizeSelection(new Point(mViewWidth - 2, 11));
assertNoSelection();
- assertEquals(NOT_SET, model.getPositionNearestOrigin());
+ assertEquals(NOT_SET, mModel.getPositionNearestOrigin());
}
+ @Test
public void testSelectionAboveItems() {
initData(20, 4);
startSelection(new Point(10, 0));
resizeSelection(new Point(11, 1));
assertNoSelection();
- assertEquals(NOT_SET, model.getPositionNearestOrigin());
+ assertEquals(NOT_SET, mModel.getPositionNearestOrigin());
}
+ @Test
public void testSelectionBelowItems() {
initData(5, 4);
startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
assertNoSelection();
- assertEquals(NOT_SET, model.getPositionNearestOrigin());
+ assertEquals(NOT_SET, mModel.getPositionNearestOrigin());
}
+ @Test
public void testVerticalSelectionBetweenItems() {
initData(20, 4);
startSelection(new Point(106, 0));
resizeSelection(new Point(107, 200));
assertNoSelection();
- assertEquals(NOT_SET, model.getPositionNearestOrigin());
+ assertEquals(NOT_SET, mModel.getPositionNearestOrigin());
}
+ @Test
public void testHorizontalSelectionBetweenItems() {
initData(20, 4);
startSelection(new Point(0, 105));
resizeSelection(new Point(200, 106));
assertNoSelection();
- assertEquals(NOT_SET, model.getPositionNearestOrigin());
+ assertEquals(NOT_SET, mModel.getPositionNearestOrigin());
}
+ @Test
public void testGrowingAndShrinkingSelection() {
initData(20, 4);
startSelection(new Point(0, 0));
@@ -180,14 +169,15 @@
resizeSelection(new Point(0, 0));
verifySelection();
- assertEquals(NOT_SET, model.getPositionNearestOrigin());
+ assertEquals(NOT_SET, mModel.getPositionNearestOrigin());
}
+ @Test
public void testSelectionMovingAroundOrigin() {
initData(16, 4);
startSelection(new Point(210, 210));
- resizeSelection(new Point(viewWidth - 1, 0));
+ resizeSelection(new Point(mViewWidth - 1, 0));
verifySelection();
resizeSelection(new Point(0, 0));
@@ -196,14 +186,15 @@
resizeSelection(new Point(0, 420));
verifySelection();
- resizeSelection(new Point(viewWidth - 1, 420));
+ resizeSelection(new Point(mViewWidth - 1, 420));
verifySelection();
// This is manually figured and will need to be adjusted if the separator position is
// changed.
- assertEquals(7, model.getPositionNearestOrigin());
+ assertEquals(7, mModel.getPositionNearestOrigin());
}
+ @Test
public void testScrollingBandSelect() {
initData(40, 4);
@@ -226,7 +217,37 @@
resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
verifySelection();
- assertEquals(0, model.getPositionNearestOrigin());
+ assertEquals(0, mModel.getPositionNearestOrigin());
+ }
+
+ private void initData(final int numChildren, int numColumns) {
+ mHost = new TestHost(numChildren, numColumns);
+ mAdapter = new TestAdapter() {
+ @Override
+ public String getStableId(int position) {
+ return Integer.toString(position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return numChildren;
+ }
+ };
+
+ mViewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX);
+
+ mModel = new GridModel(
+ mHost,
+ new TestStableIdProvider(mAdapter),
+ SelectionPredicates.CAN_SET_ANYTHING);
+
+ mModel.addOnSelectionChangedListener(
+ new GridModel.SelectionObserver() {
+ @Override
+ public void onSelectionChanged(Set<String> updatedSelection) {
+ mLastSelection = updatedSelection;
+ }
+ });
}
/** Returns the current selection area as a Rect. */
@@ -244,43 +265,43 @@
/** Asserts that the selection is currently empty. */
private void assertNoSelection() {
- assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(),
- 0, lastSelection.size());
+ assertEquals("Unexpected items " + mLastSelection + " in selection " + getSelectionArea(),
+ 0, mLastSelection.size());
}
/** Verifies the selection using actual bbox checks. */
private void verifySelection() {
Rect selectionArea = getSelectionArea();
- for (TestEnvironment.Item item: env.items) {
+ for (TestHost.Item item: mHost.items) {
if (Rect.intersects(selectionArea, item.rect)) {
assertTrue("Expected item " + item + " was not in selection " + selectionArea,
- lastSelection.contains(item.name));
+ mLastSelection.contains(item.name));
} else {
assertFalse("Unexpected item " + item + " in selection" + selectionArea,
- lastSelection.contains(item.name));
+ mLastSelection.contains(item.name));
}
}
}
private void startSelection(Point p) {
- model.startSelection(p);
- mSelectionOrigin = env.createAbsolutePoint(p);
+ mModel.startCapturing(p);
+ mSelectionOrigin = mHost.createAbsolutePoint(p);
}
private void resizeSelection(Point p) {
- model.resizeSelection(p);
- mSelectionPoint = env.createAbsolutePoint(p);
+ mModel.resizeSelection(p);
+ mSelectionPoint = mHost.createAbsolutePoint(p);
}
private void scroll(int dy) {
- assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight());
- env.verticalOffset += dy;
+ assertTrue(mHost.verticalOffset + VIEWPORT_HEIGHT + dy <= mHost.getTotalHeight());
+ mHost.verticalOffset += dy;
// Correct the cached selection point as well.
mSelectionPoint.y += dy;
- model.onScrolled(null, 0, dy);
+ mHost.mScrollListener.onScrolled(null, 0, dy);
}
- private static final class TestEnvironment implements BandController.SelectionEnvironment {
+ private static final class TestHost extends BandHost {
private final int mNumColumns;
private final int mNumRows;
@@ -291,7 +312,10 @@
public int verticalOffset = 0;
private List<Item> items = new ArrayList<>();
- public TestEnvironment(int numChildren, int numColumns) {
+ // Installed by GridModel on construction.
+ private @Nullable OnScrollListener mScrollListener;
+
+ public TestHost(int numChildren, int numColumns) {
mNumChildren = numChildren;
mNumColumns = numColumns;
mSeparatorPosition = mNumColumns + 1;
@@ -363,7 +387,9 @@
}
@Override
- public void addOnScrollListener(OnScrollListener listener) {}
+ public void addOnScrollListener(OnScrollListener listener) {
+ mScrollListener = listener;
+ }
@Override
public void removeOnScrollListener(OnScrollListener listener) {}
@@ -458,6 +484,7 @@
rect = r;
}
+ @Override
public String toString() {
return name + ": " + rect;
}
diff --git a/tests/unit/com/android/documentsui/selection/MouseInputHandlerTest.java b/tests/unit/com/android/documentsui/selection/MouseInputHandlerTest.java
new file mode 100644
index 0000000..f1bf556
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/MouseInputHandlerTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static com.android.documentsui.testing.TestEvents.Mouse.ALT_CLICK;
+import static com.android.documentsui.testing.TestEvents.Mouse.CLICK;
+import static com.android.documentsui.testing.TestEvents.Mouse.CTRL_CLICK;
+import static com.android.documentsui.testing.TestEvents.Mouse.SECONDARY_CLICK;
+import static com.android.documentsui.testing.TestEvents.Mouse.SHIFT_CLICK;
+import static com.android.documentsui.testing.TestEvents.Mouse.TERTIARY_CLICK;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.testing.SelectionHelpers;
+import com.android.documentsui.selection.testing.SelectionProbe;
+import com.android.documentsui.selection.testing.TestData;
+import com.android.documentsui.selection.testing.TestEvents;
+import com.android.documentsui.selection.testing.TestMouseCallbacks;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class MouseInputHandlerTest {
+
+ private static final List<String> ITEMS = TestData.create(100);
+
+ private MouseInputHandler mInputDelegate;
+ private TestMouseCallbacks mCallbacks;
+ private TestItemDetailsLookup mDetailsLookup;
+ private SelectionProbe mSelection;
+ private SelectionHelper mSelectionMgr;
+
+ private TestEvents.Builder mEvent;
+
+ @Before
+ public void setUp() {
+
+ mSelectionMgr = SelectionHelpers.createTestInstance(ITEMS);
+ mDetailsLookup = new TestItemDetailsLookup();
+ mSelection = new SelectionProbe(mSelectionMgr);
+
+ mCallbacks = new TestMouseCallbacks();
+ mInputDelegate = new MouseInputHandler(mSelectionMgr, mDetailsLookup, mCallbacks);
+
+ mEvent = TestEvents.builder().mouse();
+ mDetailsLookup.initAt(RecyclerView.NO_POSITION);
+ }
+
+ @Test
+ public void testConfirmedClick_StartsSelection() {
+ mDetailsLookup.initAt(11).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mSelection.assertSelection(11);
+ }
+
+ @Test
+ public void testClickOnSelectRegion_AddsToSelection() {
+ mDetailsLookup.initAt(11).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(10).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapUp(CLICK);
+
+ mSelection.assertSelected(10, 11);
+ }
+
+ @Test
+ public void testClickOnIconOfSelectedItem_RemovesFromSelection() {
+ mDetailsLookup.initAt(8).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+ mSelection.assertSelected(8, 9, 10, 11);
+
+ mDetailsLookup.initAt(9);
+ mInputDelegate.onSingleTapUp(CLICK);
+ mSelection.assertSelected(8, 10, 11);
+ }
+
+ @Test
+ public void testRightClickDown_StartsContextMenu() {
+ mInputDelegate.onDown(SECONDARY_CLICK);
+
+ mCallbacks.assertLastEvent(SECONDARY_CLICK);
+ }
+
+ @Test
+ public void testAltClickDown_StartsContextMenu() {
+ mInputDelegate.onDown(ALT_CLICK);
+
+ mCallbacks.assertLastEvent(ALT_CLICK);
+ }
+
+ @Test
+ public void testScroll_shouldTrap() {
+ mDetailsLookup.initAt(0);
+ assertTrue(mInputDelegate.onScroll(
+ null,
+ mEvent.action(MotionEvent.ACTION_MOVE).primary().build(),
+ -1,
+ -1));
+ }
+
+ @Test
+ public void testScroll_NoTrapForTwoFinger() {
+ mDetailsLookup.initAt(0);
+ assertFalse(mInputDelegate.onScroll(
+ null,
+ mEvent.action(MotionEvent.ACTION_MOVE).build(),
+ -1,
+ -1));
+ }
+
+ @Test
+ public void testUnconfirmedCtrlClick_AddsToExistingSelection() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(CTRL_CLICK);
+
+ mSelection.assertSelection(7, 11);
+ }
+
+ @Test
+ public void testUnconfirmedShiftClick_ExtendsSelection() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertSelection(7, 8, 9, 10, 11);
+ }
+
+ @Test
+ public void testConfirmedShiftClick_ExtendsSelectionFromOriginFocus() {
+ TestItemDetails item = mDetailsLookup.initAt(7);
+ mCallbacks.focusItem(item);
+
+ // This is a hack-y test, since the real FocusManager would've set range begin itself.
+ mSelectionMgr.anchorRange(7);
+ mSelection.assertNoSelection();
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapConfirmed(SHIFT_CLICK);
+ mSelection.assertSelection(7, 8, 9, 10, 11);
+ }
+
+ @Test
+ public void testUnconfirmedShiftClick_RotatesAroundOrigin() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+ mSelection.assertSelection(7, 8, 9, 10, 11);
+
+ mDetailsLookup.initAt(5);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertSelection(5, 6, 7);
+ mSelection.assertNotSelected(8, 9, 10, 11);
+ }
+
+ @Test
+ public void testUnconfirmedShiftCtrlClick_Combination() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+ mSelection.assertSelection(7, 8, 9, 10, 11);
+
+ mDetailsLookup.initAt(5);
+ mInputDelegate.onSingleTapUp(CTRL_CLICK);
+
+ mSelection.assertSelection(5, 7, 8, 9, 10, 11);
+ }
+
+ @Test
+ public void testUnconfirmedShiftCtrlClick_ShiftTakesPriority() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(mEvent.ctrl().shift().build());
+
+ mSelection.assertSelection(7, 8, 9, 10, 11);
+ }
+
+ // TODO: Add testSpaceBar_Previews, but we need to set a system property
+ // to have a deterministic state.
+
+ @Test
+ public void testDoubleClick_Opens() {
+ TestItemDetails doc = mDetailsLookup.initAt(11);
+ mInputDelegate.onDoubleTap(CLICK);
+
+ mCallbacks.assertActivated(doc);
+ }
+
+ @Test
+ public void testMiddleClick_DoesNothing() {
+ mDetailsLookup.initAt(11).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(TERTIARY_CLICK);
+
+ mSelection.assertNoSelection();
+ }
+
+ @Test
+ public void testClickOff_ClearsSelection() {
+ mDetailsLookup.initAt(11).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(RecyclerView.NO_POSITION);
+ mInputDelegate.onSingleTapUp(CLICK);
+
+ mSelection.assertNoSelection();
+ }
+
+ @Test
+ public void testClick_Focuses() {
+ mDetailsLookup.initAt(11).setInItemSelectRegion(false);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mCallbacks.assertHasFocus(true);
+ mCallbacks.assertFocused("11");
+ }
+
+ @Test
+ public void testClickOff_ClearsFocus() {
+ mDetailsLookup.initAt(11).setInItemSelectRegion(false);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+ mCallbacks.assertHasFocus(true);
+
+ mDetailsLookup.initAt(RecyclerView.NO_POSITION);
+ mInputDelegate.onSingleTapUp(CLICK);
+ mCallbacks.assertHasFocus(false);
+ }
+
+ @Test
+ public void testClickOffSelection_RemovesSelectionAndFocuses() {
+ mDetailsLookup.initAt(1).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(5);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertSelection(1, 2, 3, 4, 5);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(CLICK);
+
+ mCallbacks.assertFocused("11");
+ mSelection.assertNoSelection();
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/MouseInputHandler_RangeTest.java b/tests/unit/com/android/documentsui/selection/MouseInputHandler_RangeTest.java
new file mode 100644
index 0000000..939e778
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/MouseInputHandler_RangeTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static com.android.documentsui.testing.TestEvents.Mouse.CLICK;
+import static com.android.documentsui.testing.TestEvents.Mouse.SECONDARY_CLICK;
+import static com.android.documentsui.testing.TestEvents.Mouse.SHIFT_CLICK;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.testing.SelectionHelpers;
+import com.android.documentsui.selection.testing.SelectionProbe;
+import com.android.documentsui.selection.testing.TestData;
+import com.android.documentsui.selection.testing.TestMouseCallbacks;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+/**
+ * MouseInputDelegate / SelectHelper integration test covering the shared
+ * responsibility of range selection.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class MouseInputHandler_RangeTest {
+
+ private static final List<String> ITEMS = TestData.create(100);
+
+ private MouseInputHandler mInputDelegate;
+ private SelectionHelper mSelectionMgr;
+ private SelectionProbe mSelection;
+ private TestMouseCallbacks mCallbacks;
+ private TestItemDetailsLookup mDetailsLookup;
+
+ @Before
+ public void setUp() {
+ mSelectionMgr = SelectionHelpers.createTestInstance(ITEMS);
+ mDetailsLookup = new TestItemDetailsLookup();
+ mSelection = new SelectionProbe(mSelectionMgr);
+
+ mCallbacks = new TestMouseCallbacks();
+ mInputDelegate = new MouseInputHandler(mSelectionMgr, mDetailsLookup, mCallbacks);
+ }
+
+ @Test
+ public void testExtendRange() {
+ // uni-click just focuses.
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertRangeSelection(7, 11);
+ }
+
+ @Test
+ public void testExtendRangeContinues() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mDetailsLookup.initAt(21);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertRangeSelection(7, 21);
+ }
+
+ @Test
+ public void testMultipleContiguousRanges() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ // click without shift sets a new range start point.
+ TestItemDetails item = mDetailsLookup.initAt(20);
+ mInputDelegate.onSingleTapUp(CLICK);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mCallbacks.focusItem(item);
+
+ mDetailsLookup.initAt(25);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+ mInputDelegate.onSingleTapConfirmed(SHIFT_CLICK);
+
+ mSelection.assertRangeNotSelected(7, 11);
+ mSelection.assertRangeSelected(20, 25);
+ mSelection.assertSelectionSize(6);
+ }
+
+ @Test
+ public void testReducesSelectionRange() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(17);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mDetailsLookup.initAt(10);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertRangeSelection(7, 10);
+ }
+
+ @Test
+ public void testReducesSelectionRange_Reverse() {
+ mDetailsLookup.initAt(17).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(7);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mDetailsLookup.initAt(14);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertRangeSelection(14, 17);
+ }
+
+ @Test
+ public void testExtendsRange_Reverse() {
+ mDetailsLookup.initAt(12).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(5);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertRangeSelection(5, 12);
+ }
+
+ @Test
+ public void testExtendsRange_ReversesAfterForwardClick() {
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapConfirmed(CLICK);
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mDetailsLookup.initAt(0);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertRangeSelection(0, 7);
+ }
+
+ @Test
+ public void testRightClickEstablishesRange() {
+
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onDown(SECONDARY_CLICK);
+ // This next method call simulates the behavior of the system event dispatch code.
+ // UserInputHandler depends on a specific sequence of events for internal
+ // state to remain valid. It's not an awesome arrangement, but it is currently
+ // necessary.
+ //
+ // See: UserInputHandler.MouseDelegate#mHandledOnDown;
+ mInputDelegate.onSingleTapUp(SECONDARY_CLICK);
+
+ mDetailsLookup.initAt(11);
+ // Now we can send a subsequent event that should extend selection.
+ mInputDelegate.onDown(SHIFT_CLICK);
+ mInputDelegate.onSingleTapUp(SHIFT_CLICK);
+
+ mSelection.assertRangeSelection(7, 11);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/SelectionManagerTest.java b/tests/unit/com/android/documentsui/selection/SelectionManagerTest.java
deleted file mode 100644
index 987780e..0000000
--- a/tests/unit/com/android/documentsui/selection/SelectionManagerTest.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.SparseBooleanArray;
-
-import com.android.documentsui.dirlist.TestDocumentsAdapter;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.dirlist.TestData;
-import com.android.documentsui.selection.Selection;
-import com.android.documentsui.testing.SelectionManagers;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SelectionManagerTest {
-
- private static final List<String> ITEMS = TestData.create(100);
-
- private final Set<String> mIgnored = new HashSet<>();
- private TestDocumentsAdapter mAdapter;
- private SelectionManager mManager;
- private TestSelectionListener mCallback;
- private TestItemSelectionListener mItemCallback;
- private SelectionProbe mSelection;
-
- @Before
- public void setUp() throws Exception {
- mCallback = new TestSelectionListener();
- mItemCallback = new TestItemSelectionListener();
- mAdapter = new TestDocumentsAdapter(ITEMS);
- mManager = SelectionManagers.createTestInstance(
- mAdapter,
- SelectionManager.MODE_MULTIPLE,
- (String id, boolean nextState) -> (!nextState || !mIgnored.contains(id)));
- mManager.addCallback(mCallback);
- mManager.addItemCallback(mItemCallback);
-
- mSelection = new SelectionProbe(mManager, mItemCallback);
-
- mIgnored.clear();
- }
-
- @Test
- public void testSelection() {
- // Check selection.
- mManager.toggleSelection(ITEMS.get(7));
- mSelection.assertSelection(7);
- // Check deselection.
- mManager.toggleSelection(ITEMS.get(7));
- mSelection.assertNoSelection();
- }
-
- @Test
- public void testSelection_DoNothingOnUnselectableItem() {
- mIgnored.add(ITEMS.get(7));
-
- mManager.toggleSelection(ITEMS.get(7));
- mSelection.assertNoSelection();
- }
-
- @Test
- public void testSelection_NotifiesSelectionChanged() {
- // Selection should notify.
- mManager.toggleSelection(ITEMS.get(7));
- mCallback.assertSelectionChanged();
- // Deselection should notify.
- mManager.toggleSelection(ITEMS.get(7));
- mCallback.assertSelectionChanged();
- }
-
- @Test
- public void testSelection_PersistsOnUpdate() {
- mManager.toggleSelection(ITEMS.get(7));
-
- mAdapter.updateTestModelIds(ITEMS);
-
- mSelection.assertSelection(7);
- }
-
- @Test
- public void testSelection_IntersectsWithNewDataSet() {
- mManager.toggleSelection(ITEMS.get(99));
- mManager.toggleSelection(ITEMS.get(7));
-
- mAdapter.updateTestModelIds(TestData.create(50));
-
- mSelection.assertSelection(7);
- }
-
- @Test
- public void testSetItemsSelected() {
- mManager.setItemsSelected(getStringIds(6, 7, 8), true);
-
- mSelection.assertRangeSelected(6, 8);
- }
-
- @Test
- public void testSetItemsSelected_SkipUnselectableItem() {
- mIgnored.add(ITEMS.get(7));
-
- mManager.setItemsSelected(getStringIds(6, 7, 8), true);
-
- mSelection.assertSelected(6);
- mSelection.assertNotSelected(7);
- mSelection.assertSelected(8);
- }
-
- @Test
- public void testRangeSelection() {
- mManager.startRangeSelection(15);
- mManager.snapRangeSelection(19);
- mSelection.assertRangeSelection(15, 19);
- }
-
- @Test
- public void testRangeSelection_SkipUnselectableItem() {
- mIgnored.add(ITEMS.get(17));
-
- mManager.startRangeSelection(15);
- mManager.snapRangeSelection(19);
-
- mSelection.assertRangeSelected(15, 16);
- mSelection.assertNotSelected(17);
- mSelection.assertRangeSelected(18, 19);
- }
-
- @Test
- public void testRangeSelection_snapExpand() {
- mManager.startRangeSelection(15);
- mManager.snapRangeSelection(19);
- mManager.snapRangeSelection(27);
- mSelection.assertRangeSelection(15, 27);
- }
-
- @Test
- public void testRangeSelection_snapContract() {
- mManager.startRangeSelection(15);
- mManager.snapRangeSelection(27);
- mManager.snapRangeSelection(19);
- mSelection.assertRangeSelection(15, 19);
- }
-
- @Test
- public void testRangeSelection_snapInvert() {
- mManager.startRangeSelection(15);
- mManager.snapRangeSelection(27);
- mManager.snapRangeSelection(3);
- mSelection.assertRangeSelection(3, 15);
- }
-
- @Test
- public void testRangeSelection_multiple() {
- mManager.startRangeSelection(15);
- mManager.snapRangeSelection(27);
- mManager.endRangeSelection();
- mManager.startRangeSelection(42);
- mManager.snapRangeSelection(57);
- mSelection.assertSelectionSize(29);
- mSelection.assertRangeSelected(15, 27);
- mSelection.assertRangeSelected(42, 57);
- }
-
- @Test
- public void testProvisionalRangeSelection() {
- mManager.startRangeSelection(13);
- mManager.snapProvisionalRangeSelection(15);
- mSelection.assertRangeSelection(13, 15);
- mManager.getSelection().applyProvisionalSelection();
- mManager.endRangeSelection();
- mSelection.assertSelectionSize(3);
- }
-
- @Test
- public void testProvisionalRangeSelection_endEarly() {
- mManager.startRangeSelection(13);
- mManager.snapProvisionalRangeSelection(15);
- mSelection.assertRangeSelection(13, 15);
-
- mManager.endRangeSelection();
- // If we end range selection prematurely for provision selection, nothing should be selected
- // except the first item
- mSelection.assertSelectionSize(1);
- }
-
- @Test
- public void testProvisionalRangeSelection_snapExpand() {
- mManager.startRangeSelection(13);
- mManager.snapProvisionalRangeSelection(15);
- mSelection.assertRangeSelection(13, 15);
- mManager.getSelection().applyProvisionalSelection();
- mManager.snapRangeSelection(18);
- mSelection.assertRangeSelection(13, 18);
- }
-
- @Test
- public void testCombinationRangeSelection_IntersectsOldSelection() {
- mManager.startRangeSelection(13);
- mManager.snapRangeSelection(15);
- mSelection.assertRangeSelection(13, 15);
-
- mManager.startRangeSelection(11);
- mManager.snapProvisionalRangeSelection(18);
- mSelection.assertRangeSelected(11, 18);
- mManager.endRangeSelection();
- mSelection.assertRangeSelected(13, 15);
- mSelection.assertRangeSelected(11, 11);
- mSelection.assertSelectionSize(4);
- }
-
- @Test
- public void testProvisionalSelection() {
- Selection s = mManager.getSelection();
- mSelection.assertNoSelection();
-
- // Mimicking band selection case -- BandController notifies item callback by itself.
- mItemCallback.onItemStateChanged(ITEMS.get(1), true);
- mItemCallback.onItemStateChanged(ITEMS.get(2), true);
-
- SparseBooleanArray provisional = new SparseBooleanArray();
- provisional.append(1, true);
- provisional.append(2, true);
- s.setProvisionalSelection(getItemIds(provisional));
- mSelection.assertSelection(1, 2);
- }
-
- @Test
- public void testProvisionalSelection_Replace() {
- Selection s = mManager.getSelection();
-
- // Mimicking band selection case -- BandController notifies item callback by itself.
- mItemCallback.onItemStateChanged(ITEMS.get(1), true);
- mItemCallback.onItemStateChanged(ITEMS.get(2), true);
- SparseBooleanArray provisional = new SparseBooleanArray();
- provisional.append(1, true);
- provisional.append(2, true);
- s.setProvisionalSelection(getItemIds(provisional));
-
- mItemCallback.onItemStateChanged(ITEMS.get(1), false);
- mItemCallback.onItemStateChanged(ITEMS.get(2), false);
- provisional.clear();
-
- mItemCallback.onItemStateChanged(ITEMS.get(3), true);
- mItemCallback.onItemStateChanged(ITEMS.get(4), true);
- provisional.append(3, true);
- provisional.append(4, true);
- s.setProvisionalSelection(getItemIds(provisional));
- mSelection.assertSelection(3, 4);
- }
-
- @Test
- public void testProvisionalSelection_IntersectsExistingProvisionalSelection() {
- Selection s = mManager.getSelection();
-
- // Mimicking band selection case -- BandController notifies item callback by itself.
- mItemCallback.onItemStateChanged(ITEMS.get(1), true);
- mItemCallback.onItemStateChanged(ITEMS.get(2), true);
- SparseBooleanArray provisional = new SparseBooleanArray();
- provisional.append(1, true);
- provisional.append(2, true);
- s.setProvisionalSelection(getItemIds(provisional));
-
- mItemCallback.onItemStateChanged(ITEMS.get(1), false);
- mItemCallback.onItemStateChanged(ITEMS.get(2), false);
- provisional.clear();
-
- mItemCallback.onItemStateChanged(ITEMS.get(1), true);
- provisional.append(1, true);
- s.setProvisionalSelection(getItemIds(provisional));
- mSelection.assertSelection(1);
- }
-
- @Test
- public void testProvisionalSelection_Apply() {
- Selection s = mManager.getSelection();
-
- // Mimicking band selection case -- BandController notifies item callback by itself.
- mItemCallback.onItemStateChanged(ITEMS.get(1), true);
- mItemCallback.onItemStateChanged(ITEMS.get(2), true);
- SparseBooleanArray provisional = new SparseBooleanArray();
- provisional.append(1, true);
- provisional.append(2, true);
- s.setProvisionalSelection(getItemIds(provisional));
- s.applyProvisionalSelection();
-
- mSelection.assertSelection(1, 2);
- }
-
- @Test
- public void testProvisionalSelection_Cancel() {
- mManager.toggleSelection(ITEMS.get(1));
- mManager.toggleSelection(ITEMS.get(2));
- Selection s = mManager.getSelection();
-
- SparseBooleanArray provisional = new SparseBooleanArray();
- provisional.append(3, true);
- provisional.append(4, true);
- s.setProvisionalSelection(getItemIds(provisional));
- s.cancelProvisionalSelection();
-
- // Original selection should remain.
- mSelection.assertSelection(1, 2);
- }
-
- @Test
- public void testProvisionalSelection_IntersectsAppliedSelection() {
- mManager.toggleSelection(ITEMS.get(1));
- mManager.toggleSelection(ITEMS.get(2));
- Selection s = mManager.getSelection();
-
- // Mimicking band selection case -- BandController notifies item callback by itself.
- mItemCallback.onItemStateChanged(ITEMS.get(3), true);
- SparseBooleanArray provisional = new SparseBooleanArray();
- provisional.append(2, true);
- provisional.append(3, true);
- s.setProvisionalSelection(getItemIds(provisional));
- mSelection.assertSelection(1, 2, 3);
- }
-
- private static Set<String> getItemIds(SparseBooleanArray selection) {
- Set<String> ids = new HashSet<>();
-
- int count = selection.size();
- for (int i = 0; i < count; ++i) {
- ids.add(ITEMS.get(selection.keyAt(i)));
- }
-
- return ids;
- }
-
- private static Iterable<String> getStringIds(int... ids) {
- List<String> stringIds = new ArrayList<>(ids.length);
- for (int id : ids) {
- stringIds.add(ITEMS.get(id));
- }
- return stringIds;
- }
-}
diff --git a/tests/unit/com/android/documentsui/selection/SelectionManager_SingleSelectTest.java b/tests/unit/com/android/documentsui/selection/SelectionManager_SingleSelectTest.java
deleted file mode 100644
index b25c1c0..0000000
--- a/tests/unit/com/android/documentsui/selection/SelectionManager_SingleSelectTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.selection;
-
-import static junit.framework.Assert.fail;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.documentsui.dirlist.TestData;
-import com.android.documentsui.dirlist.TestDocumentsAdapter;
-import com.android.documentsui.selection.SelectionManager;
-import com.android.documentsui.testing.SelectionManagers;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SelectionManager_SingleSelectTest {
-
- private static final List<String> ITEMS = TestData.create(100);
-
- private SelectionManager mManager;
- private TestSelectionListener mCallback;
- private TestDocumentsAdapter mAdapter;
- private SelectionProbe mSelection;
-
- @Before
- public void setUp() throws Exception {
- mCallback = new TestSelectionListener();
- mManager = SelectionManagers.createTestInstance(ITEMS, SelectionManager.MODE_SINGLE);
- mManager.addCallback(mCallback);
-
- mSelection = new SelectionProbe(mManager);
- }
-
- @Test
- public void testSimpleSelect() {
- mManager.toggleSelection(ITEMS.get(3));
- mManager.toggleSelection(ITEMS.get(4));
- mCallback.assertSelectionChanged();
- mSelection.assertSelection(4);
- }
-
- @Test
- public void testRangeSelectionNotEstablished() {
- mManager.toggleSelection(ITEMS.get(3));
- mCallback.reset();
-
- try {
- mManager.snapRangeSelection(10);
- fail("Should have thrown.");
- } catch (Exception expected) {}
-
- mCallback.assertSelectionUnchanged();
- mSelection.assertSelection(3);
- }
-}
diff --git a/tests/unit/com/android/documentsui/selection/SelectionTest.java b/tests/unit/com/android/documentsui/selection/SelectionTest.java
index ad1422a..fcf525b 100644
--- a/tests/unit/com/android/documentsui/selection/SelectionTest.java
+++ b/tests/unit/com/android/documentsui/selection/SelectionTest.java
@@ -23,8 +23,6 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.documentsui.selection.Selection;
-
import com.google.common.collect.Sets;
import org.junit.Before;
diff --git a/tests/unit/com/android/documentsui/selection/TestItemDetails.java b/tests/unit/com/android/documentsui/selection/TestItemDetails.java
new file mode 100644
index 0000000..b943247
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/TestItemDetails.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.internal.widget.RecyclerView;
+
+public final class TestItemDetails extends ItemDetails {
+
+ // DocumentsAdapter.ITEM_TYPE_DOCUMENT
+ private int mViewType = -1;
+ private int mPosition;
+ private String mStableId;
+ private boolean mInDragRegion;
+ private boolean mInSelectionHotspot;
+
+ public TestItemDetails() {
+ mPosition = RecyclerView.NO_POSITION;
+ }
+
+ public TestItemDetails(TestItemDetails source) {
+ mPosition = source.mPosition;
+ mStableId = source.mStableId;
+ mViewType = source.mViewType;
+ mInDragRegion = source.mInDragRegion;
+ mInSelectionHotspot = source.mInSelectionHotspot;
+ }
+
+ public void setViewType(int viewType) {
+ mViewType = viewType;
+ }
+
+ public void at(int position) {
+ mPosition = position; // this is both "adapter position" and "item position".
+ mStableId = (position == RecyclerView.NO_POSITION)
+ ? null
+ : String.valueOf(position);
+ }
+
+ public void setInItemDragRegion(boolean inHotspot) {
+ mInDragRegion = inHotspot;
+ }
+
+ public void setInItemSelectRegion(boolean over) {
+ mInSelectionHotspot = over;
+ }
+
+ @Override
+ public int getItemViewType() {
+ return mViewType;
+ }
+
+ @Override
+ public boolean inDragRegion(MotionEvent event) {
+ return mInDragRegion;
+ }
+
+ @Override
+ public int hashCode() {
+ return mPosition;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof TestItemDetails)) {
+ return false;
+ }
+
+ TestItemDetails other = (TestItemDetails) o;
+ return mPosition == other.mPosition
+ && mStableId == other.mStableId
+ && mViewType == other.mViewType;
+ }
+
+ @Override
+ public int getPosition() {
+ return mPosition;
+ }
+
+ @Override
+ public String getStableId() {
+ return mStableId;
+ }
+
+ @Override
+ public boolean inSelectionHotspot(MotionEvent e) {
+ return mInSelectionHotspot;
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/TestItemDetailsLookup.java b/tests/unit/com/android/documentsui/selection/TestItemDetailsLookup.java
new file mode 100644
index 0000000..982575c
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/TestItemDetailsLookup.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+
+import javax.annotation.Nullable;
+
+/**
+ * Test impl of ItemDetailsLookup.
+ */
+public class TestItemDetailsLookup extends ItemDetailsLookup {
+
+ private @Nullable TestItemDetails mDoc;
+
+ @Override
+ public boolean overItem(MotionEvent e) {
+ return getItemPosition(e) != RecyclerView.NO_POSITION;
+ }
+
+ @Override
+ public boolean overStableItem(MotionEvent e) {
+ return mDoc.getStableId() != null;
+ }
+
+ @Override
+ public boolean inItemDragRegion(MotionEvent e) {
+ return mDoc.inDragRegion(e);
+ }
+
+ @Override
+ public int getItemPosition(MotionEvent e) {
+ return mDoc.getPosition();
+ }
+
+ @Override
+ public boolean inItemSelectRegion(MotionEvent e) {
+ return mDoc.inSelectionHotspot(e);
+ }
+
+ @Override
+ public @Nullable ItemDetails getItemDetails(MotionEvent e) {
+ return mDoc;
+ }
+
+ /**
+ * Creates/installs/returns a new test document. Subsequent calls to
+ * any EventDocLookup methods will consult the newly created doc.
+ */
+ public TestItemDetails initAt(int position) {
+ TestItemDetails doc = new TestItemDetails();
+ doc.at(position);
+ mDoc = doc;
+ return doc;
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/TouchInputHandlerTest.java b/tests/unit/com/android/documentsui/selection/TouchInputHandlerTest.java
new file mode 100644
index 0000000..c39bfee
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/TouchInputHandlerTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection;
+
+import static com.android.documentsui.testing.TestEvents.Touch.TAP;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.annotation.Nullable;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+import com.android.documentsui.selection.TouchInputHandler.Callbacks;
+import com.android.documentsui.selection.testing.SelectionHelpers;
+import com.android.documentsui.selection.testing.SelectionProbe;
+import com.android.documentsui.selection.testing.TestData;
+import com.android.documentsui.selection.testing.TestSelectionPredicate;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class TouchInputHandlerTest {
+
+ private static final List<String> ITEMS = TestData.create(100);
+
+ private TouchInputHandler mInputDelegate;
+ private SelectionHelper mSelectionMgr;
+ private TestSelectionPredicate mSelectionPredicate;
+ private TestRunnable mGestureStarted;
+ private TestCallbacks mCallbacks;
+ private TestItemDetailsLookup mDetailsLookup;
+ private SelectionProbe mSelection;
+
+ @Before
+ public void setUp() {
+ mSelectionMgr = SelectionHelpers.createTestInstance(ITEMS);
+ mDetailsLookup = new TestItemDetailsLookup();
+ mSelectionPredicate = new TestSelectionPredicate();
+ mSelection = new SelectionProbe(mSelectionMgr);
+ mGestureStarted = new TestRunnable();
+ mCallbacks = new TestCallbacks();
+
+ mInputDelegate = new TouchInputHandler(
+ mSelectionMgr,
+ mDetailsLookup,
+ mSelectionPredicate,
+ mGestureStarted,
+ mCallbacks);
+ }
+
+ @Test
+ public void testTap_ActivatesWhenNoExistingSelection() {
+ ItemDetails doc = mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(TAP);
+
+ mCallbacks.assertActivated(doc);
+ }
+
+ @Test
+ public void testScroll_shouldNotBeTrapped() {
+ assertFalse(mInputDelegate.onScroll(null, TAP, -1, -1));
+ }
+
+ @Test
+ public void testLongPress_SelectsItem() {
+ mSelectionPredicate.setReturnValue(true);
+
+ mDetailsLookup.initAt(7);
+ mInputDelegate.onLongPress(TAP);
+
+ mSelection.assertSelection(7);
+ }
+
+ @Test
+ public void testLongPress_StartsGestureSelection() {
+ mSelectionPredicate.setReturnValue(true);
+
+ mDetailsLookup.initAt(7);
+ mInputDelegate.onLongPress(TAP);
+ mGestureStarted.assertRan();
+ }
+
+ @Test
+ public void testSelectHotspot_StartsSelectionMode() {
+ mSelectionPredicate.setReturnValue(true);
+
+ mDetailsLookup.initAt(7).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapUp(TAP);
+
+ mSelection.assertSelection(7);
+ }
+
+ @Test
+ public void testSelectionHotspot_UnselectsSelectedItem() {
+ mSelectionMgr.select("11");
+
+ mDetailsLookup.initAt(11).setInItemSelectRegion(true);
+ mInputDelegate.onSingleTapUp(TAP);
+
+ mSelection.assertNoSelection();
+ }
+
+ @Test
+ public void testStartsSelection_PerformsHapticFeedback() {
+ mSelectionPredicate.setReturnValue(true);
+
+ mDetailsLookup.initAt(7);
+ mInputDelegate.onLongPress(TAP);
+
+ mCallbacks.assertVibrated();
+ }
+
+ @Test
+ public void testLongPress_AddsToSelection() {
+ mSelectionPredicate.setReturnValue(true);
+
+ mDetailsLookup.initAt(7);
+ mInputDelegate.onLongPress(TAP);
+
+ mDetailsLookup.initAt(99);
+ mInputDelegate.onLongPress(TAP);
+
+ mDetailsLookup.initAt(13);
+ mInputDelegate.onLongPress(TAP);
+
+ mSelection.assertSelection(7, 13, 99);
+ }
+
+ @Test
+ public void testTap_UnselectsSelectedItem() {
+ mSelectionMgr.select("11");
+
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(TAP);
+
+ mSelection.assertNoSelection();
+ }
+
+ @Test
+ public void testTapOff_ClearsSelection() {
+ mSelectionMgr.select("7");
+ mDetailsLookup.initAt(7);
+
+ mInputDelegate.onLongPress(TAP);
+
+ mSelectionMgr.select("11");
+ mDetailsLookup.initAt(11);
+ mInputDelegate.onSingleTapUp(TAP);
+
+ mDetailsLookup.initAt(RecyclerView.NO_POSITION).setInItemSelectRegion(false);
+ mInputDelegate.onSingleTapUp(TAP);
+
+ mSelection.assertNoSelection();
+ }
+
+ private static final class TestCallbacks extends TouchInputHandler.Callbacks {
+
+ private @Nullable ItemDetails mActivated;
+ private boolean mVibrated;
+
+ @Override
+ public boolean onItemActivated(ItemDetails item, MotionEvent e) {
+ mActivated = item;
+ return false;
+ }
+
+ @Override
+ public boolean onDragInitiated(MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ mVibrated = true;
+ }
+
+ private void assertActivated(ItemDetails expected) {
+ assertEquals(expected, mActivated);
+ }
+
+ private void assertVibrated() {
+ assertTrue(mVibrated);
+ }
+ }
+
+ private static final class TestRunnable implements Runnable {
+
+ private boolean mWasRun;
+
+ @Override
+ public void run() {
+ mWasRun = true;
+ }
+
+ void assertRan() {
+ assertTrue(mWasRun);
+ }
+ }
+}
diff --git a/tests/unit/com/android/documentsui/ui/ViewAutoScrollerTest.java b/tests/unit/com/android/documentsui/selection/ViewAutoScrollerTest.java
similarity index 88%
rename from tests/unit/com/android/documentsui/ui/ViewAutoScrollerTest.java
rename to tests/unit/com/android/documentsui/selection/ViewAutoScrollerTest.java
index 5ad5e3c..b75c3da 100644
--- a/tests/unit/com/android/documentsui/ui/ViewAutoScrollerTest.java
+++ b/tests/unit/com/android/documentsui/selection/ViewAutoScrollerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.documentsui.ui;
+package com.android.documentsui.selection;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -23,7 +23,8 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.documentsui.ui.ViewAutoScroller;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollHost;
+import com.android.documentsui.selection.ViewAutoScroller.ScrollerCallbacks;
import org.junit.Before;
import org.junit.Test;
@@ -46,15 +47,16 @@
private ViewAutoScroller mAutoScroller;
private Point mPoint;
private boolean mActive;
- private ViewAutoScroller.ScrollDistanceDelegate mDistanceDelegate;
- private ViewAutoScroller.ScrollActionDelegate mActionDelegate;
+ private ScrollHost mHost;
+ private ScrollerCallbacks mCallbacks;
private IntConsumer mScrollAssert;
@Before
public void setUp() {
mActive = false;
mPoint = new Point();
- mDistanceDelegate = new ViewAutoScroller.ScrollDistanceDelegate() {
+
+ mHost = new ScrollHost() {
@Override
public boolean isActive() {
return mActive;
@@ -70,7 +72,8 @@
return mPoint;
}
};
- mActionDelegate = new ViewAutoScroller.ScrollActionDelegate() {
+
+ mCallbacks = new ScrollerCallbacks() {
@Override
public void scrollBy(int dy) {
mScrollAssert.accept(dy);
@@ -84,7 +87,8 @@
public void removeCallback(Runnable r) {
}
};
- mAutoScroller = new ViewAutoScroller(mDistanceDelegate, mActionDelegate);
+
+ mAutoScroller = new ViewAutoScroller(mHost, mCallbacks);
}
@Test
diff --git a/tests/unit/com/android/documentsui/selection/testing/SelectionHelpers.java b/tests/unit/com/android/documentsui/selection/testing/SelectionHelpers.java
new file mode 100644
index 0000000..6bdd18a
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/SelectionHelpers.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection.testing;
+
+import com.android.documentsui.selection.DefaultSelectionHelper;
+import com.android.documentsui.selection.DefaultSelectionHelper.SelectionMode;
+import com.android.documentsui.selection.SelectionHelper;
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SelectionHelpers {
+
+ public static final SelectionPredicate CAN_SET_ANYTHING = new SelectionPredicate() {
+ @Override
+ public boolean canSetStateForId(String id, boolean nextState) {
+ return true;
+ }
+
+ @Override
+ public boolean canSetStateAtPosition(int position, boolean nextState) {
+ return true;
+ }
+ };
+
+ private SelectionHelpers() {}
+
+ public static SelectionHelper createTestInstance() {
+ return createTestInstance(Collections.emptyList());
+ }
+
+ public static SelectionHelper createTestInstance(List<String> docs) {
+ return createTestInstance(docs, DefaultSelectionHelper.MODE_MULTIPLE);
+ }
+
+ public static SelectionHelper createTestInstance(
+ List<String> items, @SelectionMode int mode) {
+ return createTestInstance(new TestAdapter(items), mode, CAN_SET_ANYTHING);
+ }
+
+ public static SelectionHelper createTestInstance(
+ TestAdapter adapter, @SelectionMode int mode, SelectionPredicate selPredicate) {
+ return new DefaultSelectionHelper(
+ mode, adapter, new TestStableIdProvider(adapter), selPredicate);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/testing/SelectionPredicates.java b/tests/unit/com/android/documentsui/selection/testing/SelectionPredicates.java
new file mode 100644
index 0000000..0200919
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/SelectionPredicates.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.testing;
+
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+/**
+ * Test friendly {@link SelectionPredicate} instances.
+ */
+public final class SelectionPredicates {
+
+ private SelectionPredicates() {}
+
+ public static final SelectionPredicate CAN_SET_ANYTHING = new SelectionPredicate() {
+ @Override
+ public boolean canSetStateForId(String id, boolean nextState) {
+ return true;
+ }
+
+ @Override
+ public boolean canSetStateAtPosition(int position, boolean nextState) {
+ return true;
+ }
+ };
+}
diff --git a/tests/common/com/android/documentsui/selection/SelectionProbe.java b/tests/unit/com/android/documentsui/selection/testing/SelectionProbe.java
similarity index 69%
rename from tests/common/com/android/documentsui/selection/SelectionProbe.java
rename to tests/unit/com/android/documentsui/selection/testing/SelectionProbe.java
index d7a3632..4d5790b 100644
--- a/tests/common/com/android/documentsui/selection/SelectionProbe.java
+++ b/tests/unit/com/android/documentsui/selection/testing/SelectionProbe.java
@@ -14,35 +14,35 @@
* limitations under the License.
*/
-package com.android.documentsui.selection;
+package com.android.documentsui.selection.testing;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import com.android.documentsui.selection.SelectionManager;
+import com.android.documentsui.selection.DefaultSelectionHelper;
import com.android.documentsui.selection.Selection;
+import com.android.documentsui.selection.SelectionHelper;
/**
- * Helper class for making assertions against the state of a {@link SelectionManager} instance and
- * the consistency of states between {@link SelectionManager} and
- * {@link SelectionManager.ItemCallback}.
+ * Helper class for making assertions against the state of a {@link DefaultSelectionHelper} instance
+ * and the consistency of states between {@link DefaultSelectionHelper} and
+ * {@link DefaultSelectionHelper.ItemEventCallback}.
*/
public final class SelectionProbe {
- private final SelectionManager mMgr;
- private final TestItemSelectionListener mTestCallback;
+ private final SelectionHelper mMgr;
+ private final TestSelectionObserver mSelectionListener;
- public SelectionProbe(SelectionManager mgr) {
+ public SelectionProbe(SelectionHelper mgr) {
mMgr = mgr;
- mTestCallback = new TestItemSelectionListener();
-
- mMgr.addItemCallback(mTestCallback);
+ mSelectionListener = new TestSelectionObserver();
+ mMgr.addObserver(mSelectionListener);
}
- public SelectionProbe(SelectionManager mgr, TestItemSelectionListener testCallback) {
+ public SelectionProbe(SelectionHelper mgr, TestSelectionObserver selectionListener) {
mMgr = mgr;
- mTestCallback = testCallback;
+ mSelectionListener = selectionListener;
}
public void assertRangeSelected(int begin, int end) {
@@ -66,20 +66,20 @@
Selection selection = mMgr.getSelection();
assertEquals(selection.toString(), expected, selection.size());
- mTestCallback.assertSelectionSize(expected);
+ mSelectionListener.assertSelectionSize(expected);
}
public void assertNoSelection() {
assertSelectionSize(0);
- mTestCallback.assertNoSelection();
+ mSelectionListener.assertNoSelection();
}
public void assertSelection(int... ids) {
assertSelected(ids);
assertEquals(ids.length, mMgr.getSelection().size());
- mTestCallback.assertSelectionSize(ids.length);
+ mSelectionListener.assertSelectionSize(ids.length);
}
public void assertSelected(int... ids) {
@@ -88,7 +88,7 @@
String sid = String.valueOf(id);
assertTrue(sid + " is not in selection " + sel, sel.contains(sid));
- mTestCallback.assertSelected(sid);
+ mSelectionListener.assertSelected(sid);
}
}
@@ -98,13 +98,13 @@
String sid = String.valueOf(id);
assertFalse(sid + " is in selection " + sel, sel.contains(sid));
- mTestCallback.assertNotSelected(sid);
+ mSelectionListener.assertNotSelected(sid);
}
}
public void select(int...positions) {
for (int position : positions) {
- mMgr.toggleSelection(String.valueOf(position));
+ mMgr.select(String.valueOf(position));
}
}
}
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestAdapter.java b/tests/unit/com/android/documentsui/selection/testing/TestAdapter.java
new file mode 100644
index 0000000..f4c6d17
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestAdapter.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.testing;
+
+import static org.junit.Assert.assertTrue;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Adapter;
+import android.support.v7.widget.RecyclerView.AdapterDataObserver;
+import android.view.ViewGroup;
+
+import com.android.documentsui.selection.SelectionHelper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class TestAdapter extends Adapter<TestHolder> {
+
+ private final List<String> mItems = new ArrayList<>();
+ private final List<Integer> mNotifiedOfSelection = new ArrayList<>();
+ private final AdapterDataObserver mAdapterObserver;
+
+ public TestAdapter() {
+ this(Collections.EMPTY_LIST);
+ }
+
+ public TestAdapter(List<String> items) {
+ mItems.addAll(items);
+ mAdapterObserver = new RecyclerView.AdapterDataObserver() {
+
+ @Override
+ public void onChanged() {
+ }
+
+ @Override
+ public void onItemRangeChanged(int startPosition, int itemCount, Object payload) {
+ if (SelectionHelper.SELECTION_CHANGED_MARKER.equals(payload)) {
+ int last = startPosition + itemCount;
+ for (int i = startPosition; i < last; i++) {
+ mNotifiedOfSelection.add(i);
+ }
+ }
+ }
+
+ @Override
+ public void onItemRangeInserted(int startPosition, int itemCount) {
+ }
+
+ @Override
+ public void onItemRangeRemoved(int startPosition, int itemCount) {
+ }
+
+ @Override
+ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ registerAdapterDataObserver(mAdapterObserver);
+ }
+
+ @Override
+ public TestHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new TestHolder(parent);
+ }
+
+ @Override
+ public void onBindViewHolder(TestHolder holder, int position) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getItemCount() {
+ return mItems.size();
+ }
+
+ public void updateTestModelIds(List<String> items) {
+ mItems.clear();
+ mItems.addAll(items);
+
+ notifyDataSetChanged();
+ }
+
+ public List<String> getStableIds() {
+ return mItems;
+ }
+
+ public int getPosition(String id) {
+ return mItems.indexOf(id);
+ }
+
+ public String getStableId(int position) {
+ return mItems.get(position);
+ }
+
+
+ public void resetSelectionNotifications() {
+ mNotifiedOfSelection.clear();
+ }
+
+ public void assertNotifiedOfSelectionChange(int position) {
+ assertTrue(mNotifiedOfSelection.contains(position));
+ }
+
+ public static List<String> createItemList(int num) {
+ List<String> items = new ArrayList<>(num);
+ for (int i = 0; i < num; ++i) {
+ items.add(Integer.toString(i));
+ }
+ return items;
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestBandPredicate.java b/tests/unit/com/android/documentsui/selection/testing/TestBandPredicate.java
new file mode 100644
index 0000000..2e901a0
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestBandPredicate.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.testing;
+
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.BandPredicate;
+
+public class TestBandPredicate extends BandPredicate {
+
+ private boolean mCanInitiate = true;
+
+ public void setCanInitiate(boolean canInitiate) {
+ mCanInitiate = canInitiate;
+ }
+
+ @Override
+ public boolean canInitiate(MotionEvent e) {
+ return mCanInitiate;
+ }
+
+}
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestData.java b/tests/unit/com/android/documentsui/selection/testing/TestData.java
new file mode 100644
index 0000000..1a05990
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestData.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection.testing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestData {
+ public static List<String> create(int num) {
+ List<String> items = new ArrayList<String>(num);
+ for (int i = 0; i < num; ++i) {
+ items.add(Integer.toString(i));
+ }
+ return items;
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestEvents.java b/tests/unit/com/android/documentsui/selection/testing/TestEvents.java
new file mode 100644
index 0000000..c472adb
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestEvents.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection.testing;
+
+import android.annotation.IntDef;
+import android.graphics.Point;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Handy-dandy wrapper class to facilitate the creation of MotionEvents.
+ */
+public final class TestEvents {
+
+ /**
+ * Common mouse event types...for your convenience.
+ */
+ public static final class Mouse {
+ public static final MotionEvent CLICK =
+ TestEvents.builder().mouse().primary().build();
+ public static final MotionEvent CTRL_CLICK =
+ TestEvents.builder().mouse().primary().ctrl().build();
+ public static final MotionEvent ALT_CLICK =
+ TestEvents.builder().mouse().primary().alt().build();
+ public static final MotionEvent SHIFT_CLICK =
+ TestEvents.builder().mouse().primary().shift().build();
+ public static final MotionEvent SECONDARY_CLICK =
+ TestEvents.builder().mouse().secondary().build();
+ public static final MotionEvent TERTIARY_CLICK =
+ TestEvents.builder().mouse().tertiary().build();
+ }
+
+ /**
+ * Common touch event types...for your convenience.
+ */
+ public static final class Touch {
+ public static final MotionEvent TAP =
+ TestEvents.builder().touch().build();
+ }
+
+ static final int ACTION_UNSET = -1;
+
+ // Add other actions from MotionEvent.ACTION_ as needed.
+ @IntDef(flag = true, value = {
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_MOVE,
+ MotionEvent.ACTION_UP
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Action {}
+
+ // Add other types from MotionEvent.TOOL_TYPE_ as needed.
+ @IntDef(flag = true, value = {
+ MotionEvent.TOOL_TYPE_FINGER,
+ MotionEvent.TOOL_TYPE_MOUSE,
+ MotionEvent.TOOL_TYPE_STYLUS,
+ MotionEvent.TOOL_TYPE_UNKNOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ToolType {}
+
+ @IntDef(flag = true, value = {
+ MotionEvent.BUTTON_PRIMARY,
+ MotionEvent.BUTTON_SECONDARY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Button {}
+
+ @IntDef(flag = true, value = {
+ KeyEvent.META_SHIFT_ON,
+ KeyEvent.META_CTRL_ON
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Key {}
+
+ private static final class State {
+ private @Action int mAction = ACTION_UNSET;
+ private @ToolType int mToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
+ private int mPointerCount = 1;
+ private Set<Integer> mButtons = new HashSet<>();
+ private Set<Integer> mKeys = new HashSet<>();
+ private Point mLocation = new Point(0, 0);
+ private Point mRawLocation = new Point(0, 0);
+ }
+
+ public static final Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Test event builder with convenience methods for common event attrs.
+ */
+ public static final class Builder {
+
+ private State mState = new State();
+
+ /**
+ * @param action Any action specified in {@link MotionEvent}.
+ * @return
+ */
+ public Builder action(int action) {
+ mState.mAction = action;
+ return this;
+ }
+
+ public Builder type(@ToolType int type) {
+ mState.mToolType = type;
+ return this;
+ }
+
+ public Builder location(int x, int y) {
+ mState.mLocation = new Point(x, y);
+ return this;
+ }
+
+ public Builder rawLocation(int x, int y) {
+ mState.mRawLocation = new Point(x, y);
+ return this;
+ }
+
+ public Builder pointerCount(int count) {
+ mState.mPointerCount = count;
+ return this;
+ }
+
+ /**
+ * Adds one or more button press attributes.
+ */
+ public Builder pressButton(@Button int... buttons) {
+ for (int button : buttons) {
+ mState.mButtons.add(button);
+ }
+ return this;
+ }
+
+ /**
+ * Removes one or more button press attributes.
+ */
+ public Builder releaseButton(@Button int... buttons) {
+ for (int button : buttons) {
+ mState.mButtons.remove(button);
+ }
+ return this;
+ }
+
+ /**
+ * Adds one or more key press attributes.
+ */
+ public Builder pressKey(@Key int... keys) {
+ for (int key : keys) {
+ mState.mKeys.add(key);
+ }
+ return this;
+ }
+
+ /**
+ * Removes one or more key press attributes.
+ */
+ public Builder releaseKey(@Button int... keys) {
+ for (int key : keys) {
+ mState.mKeys.remove(key);
+ }
+ return this;
+ }
+
+ public Builder touch() {
+ type(MotionEvent.TOOL_TYPE_FINGER);
+ return this;
+ }
+
+ public Builder mouse() {
+ type(MotionEvent.TOOL_TYPE_MOUSE);
+ return this;
+ }
+
+ public Builder shift() {
+ pressKey(KeyEvent.META_SHIFT_ON);
+ return this;
+ }
+
+ /**
+ * Use {@link #remove(@Attribute int...)}
+ */
+ public Builder unshift() {
+ releaseKey(KeyEvent.META_SHIFT_ON);
+ return this;
+ }
+
+ public Builder ctrl() {
+ pressKey(KeyEvent.META_CTRL_ON);
+ return this;
+ }
+
+ public Builder alt() {
+ pressKey(KeyEvent.META_ALT_ON);
+ return this;
+ }
+
+ public Builder primary() {
+ pressButton(MotionEvent.BUTTON_PRIMARY);
+ releaseButton(MotionEvent.BUTTON_SECONDARY);
+ releaseButton(MotionEvent.BUTTON_TERTIARY);
+ return this;
+ }
+
+ public Builder secondary() {
+ pressButton(MotionEvent.BUTTON_SECONDARY);
+ releaseButton(MotionEvent.BUTTON_PRIMARY);
+ releaseButton(MotionEvent.BUTTON_TERTIARY);
+ return this;
+ }
+
+ public Builder tertiary() {
+ pressButton(MotionEvent.BUTTON_TERTIARY);
+ releaseButton(MotionEvent.BUTTON_PRIMARY);
+ releaseButton(MotionEvent.BUTTON_SECONDARY);
+ return this;
+ }
+
+ public MotionEvent build() {
+
+ PointerProperties[] pointers = new PointerProperties[1];
+ pointers[0] = new PointerProperties();
+ pointers[0].id = 0;
+ pointers[0].toolType = mState.mToolType;
+
+ PointerCoords[] coords = new PointerCoords[1];
+ coords[0] = new PointerCoords();
+ coords[0].x = mState.mLocation.x;
+ coords[0].y = mState.mLocation.y;
+
+ int buttons = 0;
+ for (Integer button : mState.mButtons) {
+ buttons |= button;
+ }
+
+ int keys = 0;
+ for (Integer key : mState.mKeys) {
+ keys |= key;
+ }
+
+ return MotionEvent.obtain(
+ 0, // down time
+ 1, // event time
+ mState.mAction,
+ 1, // pointerCount,
+ pointers,
+ coords,
+ keys,
+ buttons,
+ 1.0f, // x precision
+ 1.0f, // y precision
+ 0, // device id
+ 0, // edge flags
+ 0, // int source,
+ 0 // int flags
+ );
+ }
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestHolder.java b/tests/unit/com/android/documentsui/selection/testing/TestHolder.java
new file mode 100644
index 0000000..a0728fe
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.testing;
+
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.View;
+
+public class TestHolder extends ViewHolder {
+ public TestHolder(View itemView) {
+ super(itemView);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestMouseCallbacks.java b/tests/unit/com/android/documentsui/selection/testing/TestMouseCallbacks.java
new file mode 100644
index 0000000..06edc1e
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestMouseCallbacks.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.testing;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.MotionEvent;
+
+import com.android.documentsui.selection.MouseInputHandler;
+import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
+
+public final class TestMouseCallbacks extends MouseInputHandler.Callbacks {
+
+ private String mFocusItemId;
+ private int mFocusPosition;
+ private MotionEvent mLastContextEvent;
+ private ItemDetails mActivated;
+
+ @Override
+ public boolean onItemActivated(ItemDetails item, MotionEvent e) {
+ mActivated = item;
+ return true;
+ }
+
+ @Override
+ public boolean onContextClick(MotionEvent e) {
+ mLastContextEvent = e;
+ return false;
+ }
+
+ @Override
+ public void onPerformHapticFeedback() {
+ }
+
+ @Override
+ public void clearFocus() {
+ mFocusPosition = RecyclerView.NO_POSITION;
+ mFocusItemId = null;
+ }
+
+ @Override
+ public void focusItem(ItemDetails item) {
+ mFocusItemId = item.getStableId();
+ mFocusPosition = item.getPosition();
+ }
+
+ @Override
+ public int getFocusedPosition() {
+ return mFocusPosition;
+ }
+
+ @Override
+ public boolean hasFocusedItem() {
+ return mFocusItemId != null;
+ }
+
+ public void assertLastEvent(MotionEvent expected) {
+ // sadly, MotionEvent doesn't implement equals, so we compare references.
+ assertTrue(expected == mLastContextEvent);
+ }
+
+ public void assertActivated(ItemDetails expected) {
+ assertEquals(expected, mActivated);
+ }
+
+ public void assertHasFocus(boolean focused) {
+ assertEquals(focused, hasFocusedItem());
+ }
+
+ public void assertFocused(String expectedId) {
+ assertEquals(expectedId, mFocusItemId);
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestSelectionObserver.java b/tests/unit/com/android/documentsui/selection/testing/TestSelectionObserver.java
new file mode 100644
index 0000000..e75bde3
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestSelectionObserver.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.selection.testing;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.documentsui.selection.SelectionHelper.SelectionObserver;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class TestSelectionObserver extends SelectionObserver {
+
+ private final Set<String> mSelected = new HashSet<>();
+ private boolean mSelectionChanged = false;
+ private boolean mSelectionReset = false;
+ private boolean mSelectionRestored = false;
+
+ public void reset() {
+ mSelected.clear();
+ mSelectionChanged = false;
+ mSelectionReset = false;
+ }
+
+ @Override
+ public void onItemStateChanged(String id, boolean selected) {
+ if (selected) {
+ assertNotSelected(id);
+ mSelected.add(id);
+ } else {
+ assertSelected(id);
+ mSelected.remove(id);
+ }
+ }
+
+ @Override
+ public void onSelectionReset() {
+ mSelectionReset = true;
+ mSelected.clear();
+ }
+
+ @Override
+ public void onSelectionChanged() {
+ mSelectionChanged = true;
+ }
+
+ @Override
+ public void onSelectionRestored() {
+ mSelectionRestored = true;
+ }
+
+ void assertNoSelection() {
+ assertTrue(mSelected.isEmpty());
+ }
+
+ void assertSelectionSize(int expected) {
+ assertEquals(expected, mSelected.size());
+ }
+
+ void assertSelected(String id) {
+ assertTrue(id + " is not selected.", mSelected.contains(id));
+ }
+
+ void assertNotSelected(String id) {
+ assertFalse(id + " is already selected", mSelected.contains(id));
+ }
+
+ public void assertSelectionChanged() {
+ assertTrue(mSelectionChanged);
+ }
+
+ public void assertSelectionUnchanged() {
+ assertFalse(mSelectionChanged);
+ }
+
+ public void assertSelectionReset() {
+ assertTrue(mSelectionReset);
+ }
+
+ public void assertSelectionRestored() {
+ assertTrue(mSelectionRestored);
+ }
+}
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestSelectionPredicate.java b/tests/unit/com/android/documentsui/selection/testing/TestSelectionPredicate.java
new file mode 100644
index 0000000..578be3d
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestSelectionPredicate.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.testing;
+
+import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
+
+public final class TestSelectionPredicate extends SelectionPredicate {
+ private boolean mValue;
+
+ public void setReturnValue(boolean value) {
+ mValue = value;
+ }
+
+ @Override
+ public boolean canSetStateForId(String id, boolean nextState) {
+ return mValue;
+ }
+
+ @Override
+ public boolean canSetStateAtPosition(int position, boolean nextState) {
+ return mValue;
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/com/android/documentsui/selection/testing/TestStableIdProvider.java b/tests/unit/com/android/documentsui/selection/testing/TestStableIdProvider.java
new file mode 100644
index 0000000..1d50737
--- /dev/null
+++ b/tests/unit/com/android/documentsui/selection/testing/TestStableIdProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui.selection.testing;
+
+import static android.support.v4.util.Preconditions.checkArgument;
+
+import com.android.documentsui.selection.SelectionHelper.StableIdProvider;
+
+import java.util.List;
+
+/**
+ * Provides RecyclerView selection code access to stable ids backed
+ * by TestAdapter.
+ */
+public final class TestStableIdProvider extends StableIdProvider {
+
+ private final TestAdapter mAdapter;
+
+ public TestStableIdProvider(TestAdapter adapter) {
+ checkArgument(adapter != null);
+ mAdapter = adapter;
+ }
+
+ @Override
+ public String getStableId(int position) {
+ return mAdapter.getStableId(position);
+ }
+
+ @Override
+ public int getPosition(String id) {
+ return mAdapter.getPosition(id);
+ }
+
+ @Override
+ public List<String> getStableIds() {
+ return mAdapter.getStableIds();
+ }
+}
diff --git a/tests/unit/com/android/documentsui/services/FileOperationServiceTest.java b/tests/unit/com/android/documentsui/services/FileOperationServiceTest.java
index 7f75aa5..a210c0e 100644
--- a/tests/unit/com/android/documentsui/services/FileOperationServiceTest.java
+++ b/tests/unit/com/android/documentsui/services/FileOperationServiceTest.java
@@ -21,8 +21,8 @@
import static com.android.documentsui.services.FileOperations.createBaseIntent;
import static com.android.documentsui.services.FileOperations.createJobId;
import static com.google.android.collect.Lists.newArrayList;
+import static org.junit.Assert.fail;
-import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -131,8 +131,9 @@
public void testRunsCopyJobs_AfterExceptionInJobCreation() throws Exception {
try {
startService(createCopyIntent(new ArrayList<>(), BETA_DOC));
- } catch(AssertionError e) {
- // Expected AssertionError
+ fail("Should have throw exception.");
+ } catch(IllegalArgumentException expected) {
+ // We're sending a naughty empty list that should result in an IllegalArgumentException.
}
startService(createCopyIntent(newArrayList(GAMMA_DOC), DELTA_DOC));