(R.id.learnMore)
22 | learnMore.setOnClickListener { v ->
23 | // This is a hardcoded link: if we ever end up needing more of these links, we should
24 | // move the link into an xml parameter, but there's no advantage to making it configurable now.
25 | val url = getTelemetryDataUsageUrl(context)
26 |
27 | val intent = Intent()
28 | intent.action = Intent.ACTION_VIEW
29 | intent.data = Uri.parse(url)
30 | context.startActivity(intent)
31 | }
32 |
33 | super.onBindViewHolder(holder)
34 | }
35 |
36 | private fun getTelemetryDataUsageUrl(context: Context): String {
37 | return context.getString(R.string.telemetry_data_usage_url,
38 | getAppVersion(context),
39 | getLanguageTag(Locale.getDefault()))
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/setting/YourRightsFragment.kt:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer.setting
2 |
3 | import android.os.Bundle
4 | import android.text.Html
5 | import android.text.method.LinkMovementMethod
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import android.widget.TextView
10 | import androidx.appcompat.app.ActionBar
11 | import androidx.fragment.app.Fragment
12 | import org.mozilla.scryer.R
13 | import org.mozilla.scryer.getSupportActionBar
14 |
15 | class YourRightsFragment : Fragment() {
16 | companion object {
17 | const val TAG: String = "YourRightsFragment"
18 | }
19 |
20 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
21 | val view: View = inflater.inflate(R.layout.fragment_your_rights, container, false)
22 |
23 | val content = StringBuilder()
24 | content.apply {
25 | append("").append(getString(R.string.your_rights_content_1, getString(R.string.app_full_name))).append("
")
26 | append("").append(getString(R.string.your_rights_content_2, getString(R.string.app_full_name))).append("
")
27 | append("").append(getString(R.string.your_rights_content_3, getString(R.string.about_privacy_notice_url))).append("
")
28 | append("").append(getString(R.string.your_rights_content_4, getString(R.string.app_full_name))).append("
")
29 | }
30 |
31 | val yourRightsTextView = view.findViewById(R.id.your_rights_content)
32 | yourRightsTextView?.text = Html.fromHtml(content.toString())
33 | yourRightsTextView?.movementMethod = LinkMovementMethod.getInstance()
34 |
35 | return view
36 | }
37 |
38 | override fun onActivityCreated(savedInstanceState: Bundle?) {
39 | super.onActivityCreated(savedInstanceState)
40 | setupActionBar()
41 | }
42 |
43 | private fun setupActionBar() {
44 | getSupportActionBar(activity).apply {
45 | setDisplayHomeAsUpEnabled(true)
46 | updateActionBarTitle(this)
47 | }
48 | }
49 |
50 | private fun updateActionBarTitle(actionBar: ActionBar) {
51 | actionBar.title = getString(R.string.about_list_right)
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/telemetry/CaptureServiceHeartbeatWorker.kt:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer.telemetry
2 |
3 | import android.app.ActivityManager
4 | import android.content.Context
5 | import androidx.work.Worker
6 | import androidx.work.WorkerParameters
7 | import org.mozilla.scryer.ScryerService
8 |
9 |
10 | class CaptureServiceHeartbeatWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) {
11 |
12 | companion object {
13 | const val TAG = "CaptureServiceHeartbeatWorker"
14 | }
15 |
16 | override fun doWork(): Result {
17 |
18 | if (isCaptureServiceRunning()) {
19 | TelemetryWrapper.logActiveBackgroundService()
20 | }
21 | return Result.success()
22 | }
23 |
24 | private fun isCaptureServiceRunning(): Boolean {
25 | val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
26 | for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
27 | if (ScryerService::class.java.name == service.service.className) {
28 | return true
29 | }
30 | }
31 | return false
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/ui/BottomDialog.kt:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer.ui
2 |
3 | import android.content.Context
4 | import androidx.annotation.LayoutRes
5 | import com.google.android.material.bottomsheet.BottomSheetBehavior
6 | import com.google.android.material.bottomsheet.BottomSheetDialog
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import android.view.ViewTreeObserver
10 | import org.mozilla.scryer.R
11 |
12 | class BottomDialogFactory {
13 | companion object {
14 | fun create(context: Context, @LayoutRes layoutId: Int): BottomSheetDialog {
15 | val dialog = BottomSheetDialog(context, R.style.ScryerBottomSheetDialogTheme)
16 | val view = View.inflate(context, layoutId, null)
17 | dialog.setContentView(view, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
18 | ViewGroup.LayoutParams.WRAP_CONTENT))
19 | view.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
20 | override fun onPreDraw(): Boolean {
21 | view.viewTreeObserver.removeOnPreDrawListener(this)
22 | BottomSheetBehavior.from(view.parent as ViewGroup).peekHeight = view.measuredHeight
23 | return false
24 | }
25 | })
26 | return dialog
27 | }
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/ui/ConfirmationDialog.kt:
--------------------------------------------------------------------------------
1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 |
6 | package org.mozilla.scryer.ui
7 |
8 | import android.content.Context
9 | import android.content.DialogInterface
10 | import androidx.appcompat.app.AlertDialog
11 | import android.view.View
12 | import android.widget.TextView
13 | import org.mozilla.scryer.R
14 |
15 | class ConfirmationDialog private constructor(
16 | private val dialog: AlertDialog,
17 | val viewHolder: ViewHolder
18 | ) {
19 | companion object {
20 | fun build(
21 | context: Context,
22 | title: String,
23 | positiveButtonText: String,
24 | positiveButtonListener: DialogInterface.OnClickListener,
25 | negativeButtonText: String,
26 | negativeButtonListener: DialogInterface.OnClickListener
27 | ): ConfirmationDialog {
28 | val view = View.inflate(context, R.layout.dialog_confirmation, null)
29 | val dialog = AlertDialog.Builder(context)
30 | .setView(view)
31 | .setTitle(title)
32 | .setPositiveButton(positiveButtonText, positiveButtonListener)
33 | .setNegativeButton(negativeButtonText, negativeButtonListener)
34 | .create()
35 | val holder = ViewHolder()
36 | holder.message = view.findViewById(R.id.confirmation_message)
37 | holder.subMessage = view.findViewById(R.id.confirmation_message_content_first_line)
38 | holder.subMessage2 = view.findViewById(R.id.confirmation_message_content_second_line)
39 | return ConfirmationDialog(dialog, holder)
40 | }
41 | }
42 |
43 | fun asAlertDialog(): AlertDialog {
44 | return dialog
45 | }
46 |
47 | class ViewHolder {
48 | var message: TextView? = null
49 | var subMessage: TextView? = null
50 | var subMessage2: TextView? = null
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/ui/GridItemDecoration.kt:
--------------------------------------------------------------------------------
1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 |
6 | package org.mozilla.scryer.ui
7 |
8 | import android.graphics.Rect
9 | import android.view.View
10 | import androidx.recyclerview.widget.RecyclerView
11 |
12 | open class GridItemDecoration(private val columnCount: Int,
13 | private val left: Int,
14 | private val top: Int,
15 | private val right: Int,
16 | private val vSpace: Int,
17 | private val hSpace: Int) : RecyclerView.ItemDecoration() {
18 |
19 | constructor(columnCount: Int, space: Int) : this(columnCount, space, space, space, space, space)
20 |
21 | override fun getItemOffsets(outRect: Rect, view: View,
22 | parent: RecyclerView, state: RecyclerView.State) {
23 | val position = parent.getChildViewHolder(view).adapterPosition
24 | if (position < 0) {
25 | return
26 | }
27 |
28 | setSpaces(outRect, position)
29 | }
30 |
31 | open fun setSpaces(outRect: Rect, position: Int) {
32 | outRect.left = if (position % columnCount == 0) left else hSpace / 2
33 | outRect.top = if (position < columnCount) top else 0
34 | outRect.right = if (position % columnCount == columnCount - 1) right else hSpace / 2
35 | outRect.bottom = vSpace
36 | }
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/ui/InnerSpaceDecoration.kt:
--------------------------------------------------------------------------------
1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 |
6 | package org.mozilla.scryer.ui
7 |
8 | import android.graphics.Rect
9 | import android.view.View
10 |
11 | class InnerSpaceDecoration(private val space: Int,
12 | private val columnCountProvider: () -> Int) : androidx.recyclerview.widget.RecyclerView.ItemDecoration() {
13 | override fun getItemOffsets(outRect: Rect, view: View, parent: androidx.recyclerview.widget.RecyclerView, state: androidx.recyclerview.widget.RecyclerView.State) {
14 | /**
15 | * x: padding for left/right-most items (left-most item only have right padding, vice versa)
16 | * y: padding for middle items (padding at both left & right sides)
17 | *
18 | * size of left/right-most items must be equal to the size of middle items
19 | * x = 2y
20 | *
21 | * 2x + 2(middleItemCount)y = sum of all padding
22 | * => 2x + 2(itemCount - 2)y = space * (itemCount - 1)
23 | * => 4y + 2(itemCount - 2)y = space * (itemCount - 1)
24 | * => y = space * (itemCount - 1) / (4 + 2 * (itemCount - 2))y
25 | */
26 | val position = parent.getChildAdapterPosition(view)
27 | val columnCount = columnCountProvider.invoke()
28 | val y = space * (columnCount - 1) / (4 + 2 * (columnCount - 2))
29 | val x = y * 2
30 |
31 | outRect.top = 0
32 | outRect.bottom = space
33 | when {
34 | position % columnCount == 0 -> {
35 | outRect.left = 0
36 | outRect.right = x
37 | }
38 | position % columnCount == columnCount - 1 -> {
39 | outRect.left = x
40 | outRect.right = 0
41 | }
42 | else -> {
43 | outRect.left = y
44 | outRect.right = y
45 | }
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/ui/LockableViewPager.kt:
--------------------------------------------------------------------------------
1 | /* This Source Code Form is subject to the terms of the Mozilla Public
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 |
5 | package org.mozilla.scryer.ui
6 |
7 | import android.annotation.SuppressLint
8 | import android.content.Context
9 | import android.util.AttributeSet
10 | import android.view.MotionEvent
11 | import androidx.viewpager.widget.ViewPager
12 |
13 | class LockableViewPager : ViewPager {
14 | var pageLocked = false
15 |
16 | constructor(context: Context) : super(context)
17 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
18 |
19 | @SuppressLint("ClickableViewAccessibility")
20 | override fun onTouchEvent(ev: MotionEvent?): Boolean {
21 | if (pageLocked) {
22 | return false
23 | }
24 | return super.onTouchEvent(ev)
25 | }
26 |
27 | override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
28 | if (pageLocked) {
29 | return false
30 | }
31 | return super.onInterceptTouchEvent(ev)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/ui/ScryerSnackbar.kt:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer.ui
2 |
3 | import android.graphics.Color
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.core.content.ContextCompat
7 | import androidx.core.graphics.drawable.DrawableCompat
8 | import com.google.android.material.snackbar.Snackbar
9 | import org.mozilla.scryer.R
10 |
11 | class ScryerSnackbar {
12 | companion object {
13 |
14 | fun make(view: View, text: String, duration: Int): Snackbar {
15 | val bar = Snackbar.make(view, text, duration)
16 |
17 | ContextCompat.getDrawable(view.context, R.drawable.rect_4dp)?.apply {
18 | val wrapped = DrawableCompat.wrap(this)
19 | DrawableCompat.setTint(wrapped, ContextCompat.getColor(view.context, R.color.primaryTeal))
20 | bar.view.background = wrapped
21 |
22 | val params = bar.view.layoutParams
23 | // TODO: Visual spec for margin
24 | val margin = view.resources.getDimensionPixelSize(R.dimen.toast_horizontal_margin)
25 | if (params is ViewGroup.MarginLayoutParams) {
26 | params.marginStart = margin
27 | params.marginEnd = margin
28 | params.bottomMargin = margin
29 | }
30 | bar.view.layoutParams = params
31 | bar.setActionTextColor(Color.WHITE)
32 | }
33 |
34 | return bar
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/ui/ScryerToast.kt:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer.ui
2 |
3 | import android.content.Context
4 | import android.view.Gravity
5 | import android.view.View
6 | import android.widget.TextView
7 | import android.widget.Toast
8 | import org.mozilla.scryer.R
9 |
10 | class ScryerToast(private val context: Context) {
11 | companion object {
12 |
13 | /**
14 | * Use ScryerToast#show() if you're likely to show toast multiple times within the same page,
15 | * so the toast view can be reused instead of inflating a new one each time this method is called.
16 | */
17 | fun makeText(context: Context, text: String, duration: Int): Toast {
18 | val toast = Toast(context)
19 | toast.setGravity(Gravity.FILL_HORIZONTAL or Gravity.BOTTOM, 0, 0)
20 | toast.view = View.inflate(context, R.layout.view_custom_toast, null)
21 | toast.view.findViewById(R.id.text)?.text = text
22 | toast.duration = duration
23 | return toast
24 | }
25 | }
26 |
27 | private var toast: Toast? = null
28 | private var rootView: View = View.inflate(context, R.layout.view_custom_toast, null)
29 | private val textView: TextView by lazy {
30 | rootView.findViewById(R.id.text)
31 | }
32 |
33 | fun show(msg: String, toastDuration: Int, yOffset: Int = 0) {
34 | textView.text = msg
35 | toast?.cancel()
36 |
37 | toast = Toast(context).apply {
38 | setGravity(Gravity.FILL_HORIZONTAL or Gravity.BOTTOM, 0, yOffset)
39 | view = rootView
40 | duration = toastDuration
41 | show()
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/util/ThreadUtils.kt:
--------------------------------------------------------------------------------
1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 |
6 | package org.mozilla.scryer.util
7 |
8 | import android.os.Looper
9 | import kotlinx.coroutines.experimental.*
10 | import java.util.concurrent.Executors
11 | import java.util.concurrent.ThreadFactory
12 | import java.util.concurrent.atomic.AtomicInteger
13 |
14 | object ThreadUtils {
15 | private val backgroundExecutorService = Executors.newSingleThreadExecutor(ioPrioritisedFactory)
16 | private val uiThread = Looper.getMainLooper().thread
17 |
18 | private val ioPrioritisedFactory: ThreadFactory
19 | get() = CustomThreadFactory("pool-io-background", Thread.NORM_PRIORITY - 1)
20 |
21 | val singleThreadDispatcher = backgroundExecutorService.asCoroutineDispatcher()
22 |
23 | fun assertOnUiThread() {
24 | val currentThread = Thread.currentThread()
25 | val currentThreadId = currentThread.id
26 | val expectedThreadId = uiThread.id
27 |
28 | if (currentThreadId == expectedThreadId) {
29 | return
30 | }
31 |
32 | throw IllegalThreadStateException("Expected UI thread, but running on " + currentThread.name)
33 | }
34 |
35 | private class CustomThreadFactory(private val threadName: String, private val threadPriority: Int) : ThreadFactory {
36 | private val mNumber = AtomicInteger()
37 |
38 | override fun newThread(r: Runnable): Thread {
39 | val thread = Thread(r, threadName + "-" + mNumber.getAndIncrement())
40 | thread.priority = threadPriority
41 | return thread
42 | }
43 | }
44 | }
45 |
46 | fun launchIO(block: suspend CoroutineScope.() -> Unit) {
47 | GlobalScope.launch(Dispatchers.IO) {
48 | block(this)
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/util/ViewUtils.kt:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer.util
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.view.inputmethod.InputMethodManager
6 |
7 | fun showKeyboard(view: View) {
8 | val imm = view.context
9 | .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
10 | imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
11 | }
12 |
13 | fun hideKeyboard(view: View) {
14 | val imm = view.context
15 | .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
16 | imm.hideSoftInputFromWindow(view.windowToken, 0)
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/org/mozilla/scryer/viewmodel/ScreenshotViewModel.kt:
--------------------------------------------------------------------------------
1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 |
6 | package org.mozilla.scryer.viewmodel
7 |
8 | import androidx.fragment.app.Fragment
9 | import androidx.fragment.app.FragmentActivity
10 | import androidx.lifecycle.ViewModel
11 | import androidx.lifecycle.ViewModelProvider
12 | import androidx.lifecycle.ViewModelProviders
13 | import kotlinx.coroutines.experimental.Dispatchers
14 | import kotlinx.coroutines.experimental.withContext
15 | import org.mozilla.scryer.ScryerApplication
16 | import org.mozilla.scryer.persistence.ScreenshotModel
17 | import org.mozilla.scryer.repository.ScreenshotRepository
18 |
19 | class ScreenshotViewModel(private val delegate: ScreenshotRepository) : ViewModel(),
20 | ScreenshotRepository by delegate {
21 | companion object {
22 | fun get(fragment: Fragment): ScreenshotViewModel {
23 | return ViewModelProviders.of(fragment, getFactory()).get(ScreenshotViewModel::class.java)
24 | }
25 |
26 | fun get(activity: FragmentActivity): ScreenshotViewModel {
27 | return ViewModelProviders.of(activity, getFactory()).get(ScreenshotViewModel::class.java)
28 | }
29 |
30 | private fun getFactory(): ScreenshotViewModelFactory {
31 | return ScreenshotViewModelFactory(ScryerApplication.getScreenshotRepository())
32 | }
33 | }
34 |
35 | suspend fun batchMove(
36 | screenshots: List,
37 | collectionId: String
38 | ) = withContext(Dispatchers.Default) {
39 | screenshots.forEach {
40 | it.collectionId = collectionId
41 | updateScreenshots(listOf(it))
42 | }
43 | }
44 | }
45 |
46 | class ScreenshotViewModelFactory(private val repository: ScreenshotRepository)
47 | : ViewModelProvider.NewInstanceFactory() {
48 | override fun create(modelClass: Class): T {
49 | @Suppress("UNCHECKED_CAST")
50 | return ScreenshotViewModel(repository) as T
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/res/anim/slid_in_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_in_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_out_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_out_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/color/primary_text_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/image_logotype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-hdpi/image_logotype.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/image_logotype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-mdpi/image_logotype.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/image_logotype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xhdpi/image_logotype.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_stat_notify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/ic_stat_notify.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_appbeta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_appbeta.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_emptypage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_emptypage.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_error.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_feedback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_feedback.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_logotype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_logotype.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_noresult.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_noresult.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_search.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_searchhint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_searchhint.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_share.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/image_welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/image_welcome.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/img_ocrhint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/img_ocrhint.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/img_pointer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/drawable-xxhdpi/img_pointer.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/add.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/back.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bottom_dialog_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/capture.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/capture_button_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/capture_button_exit_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/capture_button_exit_border.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/check.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_2dp_grey50.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_2dp_white.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/close_large.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/close_small.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/collection_name_dialog_cursor.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/contained_button_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/copy.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/debug_broken_svg.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/detailpage_toolbar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edit_close.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/error.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/fab_ocr.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/hint.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/home_new_collection_item_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/home_quick_access_empty_view_border.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_stat_notify_sort.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/more.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/move.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outlined_button_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rect_2dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rect_3dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rect_4dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/screenshot_select_checkbox.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/search.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selected.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/share.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sorted_collection_item_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sorting_panel_create_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sorting_panel_hint_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sorting_panel_item_ripple.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sorting_panel_suggest_item_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/trash.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/unsorted_collection_item_bkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/viewmore.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/websearch.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
23 |
24 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sorting_panel.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
11 |
12 |
16 |
17 |
24 |
25 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_svg_viewer.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_confirmation.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
27 |
28 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_give_feedback.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
32 |
33 |
36 |
37 |
42 |
43 |
44 |
49 |
50 |
57 |
58 |
62 |
63 |
70 |
71 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_promote.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
22 |
33 |
34 |
45 |
46 |
51 |
52 |
59 |
60 |
65 |
66 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_screenshot_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
26 |
27 |
35 |
36 |
43 |
44 |
52 |
53 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_your_rights.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/home_collection_item_container.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_collection.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
21 |
22 |
27 |
28 |
36 |
37 |
51 |
52 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_loading.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
10 |
11 |
18 |
19 |
29 |
30 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_new_collection.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
21 |
22 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_quick_access.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
17 |
18 |
25 |
31 |
32 |
33 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_quick_access_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
20 |
21 |
30 |
31 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_screenshot.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
23 |
29 |
33 |
34 |
35 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/preference_screenshot_feature_sub_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
27 |
28 |
36 |
37 |
38 |
39 |
40 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/preference_telemetry_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
26 |
27 |
35 |
36 |
44 |
45 |
46 |
47 |
48 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_capture_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_capture_button_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
26 |
27 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_custom_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_home_section_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_home_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_sorting_panel_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
29 |
30 |
44 |
45 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_collection.xml:
--------------------------------------------------------------------------------
1 |
2 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_collection_view_select_action_mode.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_detailpage_text_selection.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_sorting_panel.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi-v26/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-hdpi-v26/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi-v26/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-hdpi-v26/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/navigation/nav_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
13 |
20 |
27 |
34 |
35 |
39 |
40 |
41 |
48 |
49 |
53 |
54 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/image_notification.json:
--------------------------------------------------------------------------------
1 | {"v":"5.4.1","fr":30,"ip":0,"op":90,"w":30,"h":30,"nm":"Option2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Center","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[14.938,15.062,0],"ix":2},"a":{"a":0,"k":[-0.373,-2.857,0],"ix":1},"s":{"a":0,"k":[65.689,65.689,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[15.207,15.207],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"ml2":{"a":0,"k":4,"ix":8},"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.78431372549,0.843137254902,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-0.349,-2.905],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":91,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[1],"y":[1]},"o":{"x":[1],"y":[0]},"n":["1_1_1_0"],"t":10,"s":[60],"e":[0]},{"t":30}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[14.938,15.062,0],"ix":2},"a":{"a":0,"k":[-0.372,-2.853,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[1,1,0.83],"y":[1,1,-15.155]},"o":{"x":[1,1,0.31],"y":[0,0,0]},"n":["1_1_1_0","1_1_1_0","0p83_-15p155_0p31_0"],"t":10,"s":[65.919,65.919,100],"e":[196.949,196.949,100]},{"t":26}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[15.207,15.207],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"ml2":{"a":0,"k":4,"ix":8},"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.78431372549,0.843137254902,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-0.349,-2.905],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0}],"markers":[]}
--------------------------------------------------------------------------------
/app/src/main/res/values-land/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 3
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | @color/home_background
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v24/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #0060DF
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v28/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/app.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ScreenshotGo
4 | GO
5 | Firefox ScreenshotGo
6 |
7 | %1$d / %2$d
8 | https://qsurvey.mozilla.com/s3/Firefox-ScreenshotGo-Input
9 | https://mzl.la/2NMgD30
10 | https://support.mozilla.org/1/firefox/%1$s/Android/%2$s/screenshot-help
11 | https://support.mozilla.org/1/mobile/%1$s/Android/%2$s/usage-data
12 | https://www.mozilla.org/privacy/firefox-screenshotgo/
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
8 | #00c8d7
9 | #00e5ba
10 | #ff4c5c
11 | #0c0c0d
12 | #616161
13 | #737373
14 | #b1b1b3
15 | #ededed
16 | #f5f5f5
17 | #ffffff
18 | #52000000
19 | #00000000
20 |
21 |
22 | #3f3a4f
23 | #dddddd
24 | #d5e4d6
25 | #d7d7d7
26 | @color/grey60
27 | @color/white
28 |
29 |
30 | @color/white
31 | @color/grey10
32 | @color/disableGrey
33 |
34 |
35 | #cbcbcb
36 | #8000bac8
37 | #1a000000
38 |
39 |
40 | @color/primaryTeal
41 |
42 |
43 | #cc000000
44 |
45 |
46 | - #235dff
47 | - #10c1b6
48 | - #ffa6a8
49 | - #f8c300
50 | - #8400dc
51 | - #ffb300
52 | - #008ca0
53 | - #003689
54 | - #c5c600
55 | - #57ccd6
56 | - #ffa378
57 | - #ff7678
58 | - #729f95
59 | - #007e26
60 | - #ff5741
61 | - #e3af00
62 | - #ff5800
63 | - #00544c
64 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 20
4 | 2
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/preference_keys.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | pref_key_enable_capture_service
7 | pref_key_enable_floating_screenshot_button
8 | pref_key_enable_add_to_collection
9 | pref_key_enable_send_usage_data
10 | pref_key_give_feedback
11 | pref_key_share_with_friends
12 | pref_key_about
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings_your_rights.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | %1$s is made available to you by Mozilla under the terms of the Mozilla Public License and other permissive licenses, which means that you may use, copy, modify, and distribute portions of the codebase that are open source. Some portions of the codebase include proprietary code from Google Firebase.
5 |
6 |
8 | You are not granted any trademark rights or licenses to our trademarks, including without limitation the Mozilla, Firefox and %1$s names or logos.
9 |
10 |
12 | Privacy Notice describes what information we receive from you and how we handle that information.]]>
13 |
14 |
16 | By choosing to submit feedback on %1$s, you give us permission to use the feedback to improve our products.
17 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/fileprovider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
11 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/searchable.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
11 |
17 |
18 |
25 |
26 |
32 |
33 |
37 |
38 |
42 |
43 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/preview/res/mipmap/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/preview/res/mipmap/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/preview/res/mipmap/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/app/src/preview/res/mipmap/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/preview/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Scryer Nightly
4 |
--------------------------------------------------------------------------------
/app/src/test/java/org/mozilla/scryer/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/test/java/org/mozilla/scryer/util/CollectionListHelperTest.kt:
--------------------------------------------------------------------------------
1 | package org.mozilla.scryer.util
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 | import org.mozilla.scryer.persistence.CollectionModel
7 |
8 | class CollectionListHelperTest {
9 |
10 | @Test
11 | fun nextCollectionColor() {
12 | var collections = (0..3).map { model(it) }
13 | var colors = listOf(0, 1, 2, 3)
14 | assertEquals(0, nextCollectionColor(collections, colors, 100))
15 |
16 |
17 | collections = (0..1).map { model(it) }
18 | colors = listOf(0, 1, 2, 3)
19 | assertEquals(2, nextCollectionColor(collections, colors, 100))
20 |
21 |
22 | // Return the first color in the pool if the last collection color is an unknown color
23 | collections = listOf(
24 | model(0),
25 | model(1),
26 | model(2),
27 | model(5)
28 | )
29 | colors = listOf(0, 1, 2, 3)
30 | assertEquals(0, nextCollectionColor(collections, colors, 100))
31 |
32 |
33 | collections = listOf(
34 | model(0),
35 | model(1),
36 | model(2),
37 | model(5)
38 | )
39 | colors = listOf()
40 | assertEquals(100, nextCollectionColor(collections, colors, 100))
41 |
42 |
43 | collections = listOf()
44 | colors = listOf(1, 2, 3)
45 | assertEquals(1, nextCollectionColor(collections, colors, 100))
46 |
47 |
48 | collections = listOf()
49 | colors = listOf()
50 | assertEquals(100, nextCollectionColor(collections, colors, 100))
51 | }
52 |
53 | private fun model(color: Int): CollectionModel {
54 | return CollectionModel("", "", 0, color)
55 | }
56 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | import dependencies.Versions
4 | buildscript {
5 |
6 | repositories {
7 | google()
8 | jcenter()
9 | maven {
10 | url 'https://maven.fabric.io/public'
11 | }
12 | }
13 | dependencies {
14 | classpath "com.android.tools.build:gradle:${Versions.android_gradle_plugin}"
15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
16 | classpath "com.google.gms:google-services:${Versions.google_service_plugin}" // google-services plugin
17 | classpath "io.fabric.tools:gradle:${Versions.fabric_gradle_plugin}"
18 | classpath "com.google.android.gms:oss-licenses-plugin:${Versions.license_plugin}"
19 | // NOTE: Do not place your application dependencies here; they belong
20 | // in the individual module build.gradle files
21 | }
22 | }
23 |
24 | allprojects {
25 | repositories {
26 | google()
27 | maven {
28 | url "https://maven.mozilla.org/maven2"
29 | }
30 | jcenter()
31 | }
32 | }
33 |
34 | task clean(type: Delete) {
35 | delete rootProject.buildDir
36 | }
37 |
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | }
--------------------------------------------------------------------------------
/components/service/telemetry-annotation/build.gradle:
--------------------------------------------------------------------------------
1 | import dependencies.Versions
2 |
3 | apply plugin: 'java-library'
4 | apply plugin: 'kotlin'
5 |
6 | dependencies {
7 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Versions.kotlin}"
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/components/service/telemetry-annotation/src/main/java/org/mozilla/telemetry/annotation/TelemetryDoc.kt:
--------------------------------------------------------------------------------
1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 | package org.mozilla.telemetry.annotation
6 |
7 | import kotlin.annotation.Retention
8 |
9 |
10 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
11 | @Retention(AnnotationRetention.RUNTIME)
12 | annotation class TelemetryDoc(
13 | val name: String,
14 | val value: String,
15 | val category: String,
16 | val method: String,
17 | val `object`: String,
18 | val extras: Array)
--------------------------------------------------------------------------------
/components/service/telemetry-annotation/src/main/java/org/mozilla/telemetry/annotation/TelemetryExtra.java:
--------------------------------------------------------------------------------
1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 | package org.mozilla.telemetry.annotation;
6 |
7 | import java.lang.annotation.ElementType;
8 | import java.lang.annotation.Retention;
9 | import java.lang.annotation.RetentionPolicy;
10 | import java.lang.annotation.Target;
11 |
12 | @Target({ElementType.METHOD, ElementType.PARAMETER})
13 | @Retention(RetentionPolicy.RUNTIME)
14 | public @interface TelemetryExtra {
15 | String name();
16 |
17 | String value();
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/components/service/telemetry-compiler/build.gradle:
--------------------------------------------------------------------------------
1 | import dependencies.Versions
2 |
3 | apply plugin: 'java-library'
4 |
5 |
6 | sourceCompatibility = "7"
7 | targetCompatibility = "7"
8 |
9 |
10 | dependencies {
11 | implementation project(path: ':telemetry-annotation')
12 |
13 | testImplementation "junit:junit:${Versions.junit}"
14 | testImplementation 'com.google.testing.compile:compile-testing:0.15'
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/components/service/telemetry-compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor:
--------------------------------------------------------------------------------
1 | org.mozilla.telemetry.compiler.TelemetryAnnotationProcessor
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
15 | kotlin.coroutines=enable
16 | android.useAndroidX=true
17 | android.enableJetifier=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Dec 20 12:01:37 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | include ':telemetry-annotation'
4 | project(':telemetry-annotation').projectDir = new File('components/service/telemetry-annotation')
5 |
6 | include ':telemetry-compiler'
7 | project(':telemetry-compiler').projectDir = new File('components/service/telemetry-compiler')
8 |
--------------------------------------------------------------------------------
/tools/l10n/android2po/README.md:
--------------------------------------------------------------------------------
1 | This is an imported and forked version of android2po with some modifications to import and export
2 | files that Pontoon can handle.
3 |
4 | https://github.com/miracle2k/android2po
5 |
--------------------------------------------------------------------------------
/tools/l10n/android2po/a2po.py:
--------------------------------------------------------------------------------
1 | from program import run
2 |
3 | if __name__ == "__main__":
4 | run()
5 |
--------------------------------------------------------------------------------
/tools/l10n/android2po/commands.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/tools/l10n/android2po/commands.pyc
--------------------------------------------------------------------------------
/tools/l10n/android2po/config.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/tools/l10n/android2po/config.pyc
--------------------------------------------------------------------------------
/tools/l10n/android2po/convert.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/tools/l10n/android2po/convert.pyc
--------------------------------------------------------------------------------
/tools/l10n/android2po/env.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/tools/l10n/android2po/env.pyc
--------------------------------------------------------------------------------
/tools/l10n/android2po/program.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/tools/l10n/android2po/program.pyc
--------------------------------------------------------------------------------
/tools/l10n/android2po/requirements.txt:
--------------------------------------------------------------------------------
1 | # Install using pip install -r requirements.txt
2 |
3 | argparse
4 | babel==2.4
5 | lxml==3.8.0
6 | ordereddict
7 | termcolor
8 |
--------------------------------------------------------------------------------
/tools/l10n/android2po/utils.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla-tw/ScreenshotGo/c827ba8a40e0897d0dd3513c389ed422688e183f/tools/l10n/android2po/utils.pyc
--------------------------------------------------------------------------------
/tools/l10n/check_translations.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # This Source Code Form is subject to the terms of the Mozilla Public
4 | # License, v. 2.0. If a copy of the MPL was not distributed with this
5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 |
7 | """Check translation files for missing or wrong number of placeholders."""
8 |
9 | from os import path, walk
10 | from sys import exit
11 | import xml.etree.ElementTree as ET
12 |
13 |
14 | def etree_to_dict(tree):
15 | d = {}
16 | for element in tree.getchildren():
17 | if 'name' in element.attrib:
18 | d[element.attrib['name']] = element.text
19 | else:
20 | d.update(etree_to_dict(element))
21 | return d
22 |
23 |
24 | def raise_exception(lang, code):
25 | print(" * [{lang}/strings.xml] missing placeholder in translation, key: {code}".format(
26 | lang=lang,
27 | code=code
28 | ))
29 |
30 | PATH = path.join(path.dirname(path.abspath(__file__)), '../../app/src/main/res/')
31 | files = []
32 |
33 | # Make list of all locale xml files
34 | for directory, directories, file_names in walk(PATH):
35 | for file_name in file_names:
36 | if file_name == "strings.xml" and 'values-' in directory:
37 | files.append(
38 | path.join(directory, file_name)
39 | )
40 | # Read source file
41 | source_xml = ET.parse(path.join(PATH, 'values/strings.xml'))
42 | source = etree_to_dict(source_xml.getroot())
43 |
44 | got_error = False
45 |
46 | for source_xml in files:
47 | target = etree_to_dict(ET.parse(source_xml).getroot())
48 | print("Checking for placeholders in {lang}".format(lang=source_xml.split('/')[-2].replace('values-', '')))
49 | for key in source:
50 | # pass missing translations and empty strings
51 | if key not in target:
52 | continue
53 | if not target[key]:
54 | continue
55 | if not source[key]:
56 | continue
57 | # Check for placeholders
58 | for placeholder in ['%1$s', '%2$s', '%3$s', '%4$s', '%5$s']:
59 | if placeholder in source[key] and \
60 | source[key].count(placeholder) != target[key].count(placeholder):
61 | raise_exception(source_xml.split('/')[-2], key)
62 | got_error = True
63 |
64 | if got_error:
65 | exit(1)
66 |
--------------------------------------------------------------------------------
/tools/l10n/create_commits.sh:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | # Create a separate commit for every locale.
6 |
7 | parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
8 | cd "$parent_path/../../l10n-repo"
9 |
10 | git add locales/templates/app.pot
11 | git commit -m "template update: app.pot"
12 |
13 | cd locales
14 |
15 | locale_list=$(find . -mindepth 1 -maxdepth 1 -type d \( ! -iname ".*" \) | sed 's|^\./||g' | sort)
16 | for locale in ${locale_list};
17 | do
18 | # Exclude templates
19 | if [ "${locale}" != "templates" ]
20 | then
21 | git add ${locale}/app.po
22 | git commit -m "${locale}: Update app.po"
23 | fi
24 | done
25 |
26 |
--------------------------------------------------------------------------------
/tools/l10n/export-strings.sh:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | # If a command fails then do not proceed and fail this script too.
6 | set -e
7 |
8 | # Go to project root
9 | cd "$(dirname "$0")"
10 | cd ../..
11 |
12 | # Checkout l10n repository or update already existing checkout
13 | if [ ! -d "l10n-repo" ]; then
14 | git clone https://github.com/mozilla-l10n/scryer-android-l10n.git l10n-repo
15 | else
16 | cd l10n-repo
17 | git fetch origin
18 | cd ..
19 | fi
20 |
21 | # Reset the repo to the master state
22 | cd l10n-repo
23 | git reset --hard origin/master
24 | git checkout master
25 | git reset --hard origin/master
26 |
27 | # Create a branch for the export
28 | BRANCH="export-"`date +%Y-%m-%d`
29 | git branch -D $BRANCH || echo ""
30 | git checkout -b $BRANCH
31 | cd ..
32 |
33 | # Export strings and convert them from Android strings.xml files to po files
34 | python tools/l10n/android2po/a2po.py export || echo "Could not export all locales"
35 |
36 | # Create a separate commit for every locale.
37 | tools/l10n/create_commits.sh
38 |
39 | echo ""
40 | echo "Please push and review branch $BRANCH in l10n-repo/"
41 |
--------------------------------------------------------------------------------
/tools/l10n/fix_locale_folders.sh:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | # a2po has problems with the folder format of Pontoon and creates resource folders
6 | # like values-es-MX. Android expects values-es-rMX. This script tries to find those
7 | # folders and fixes them.
8 |
9 | parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
10 |
11 | cd "$parent_path/../../app/src/main/res/"
12 |
13 |
14 | folder_list=$(find . -maxdepth 1 -type d -iname "values-*-*")
15 | for folder in ${folder_list};
16 | do
17 | country=$(echo ${folder} | cut -d'-' -f3)
18 | len=${#country}
19 |
20 | if [ "$len" -eq "2" ]; then
21 | prefix=$(echo ${folder} | cut -d'-' -f1,2)
22 |
23 | fixed_folder="${prefix}-r${country}"
24 |
25 | echo "Fixing ${folder} -> ${fixed_folder}"
26 |
27 | # The target folder might already have some data (e.g. our urls.xml),
28 | # hence we only copy newly generated files over (and keep existing
29 | # non-generated files).
30 | if [ ! -d "${fixed_folder}" ]; then
31 | mkdir "${fixed_folder}"
32 | fi
33 |
34 | cp -r "$folder"/* "${fixed_folder}"
35 |
36 | rm -rf "$folder"
37 | fi
38 | done
39 |
40 |
--------------------------------------------------------------------------------
/tools/l10n/import-strings.sh:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | # If a command fails then do not proceed and fail this script too.
6 | set -e
7 |
8 | # Go to project root
9 | cd "$(dirname "$0")"
10 | cd ../..
11 |
12 | # Checkout l10n repository or update already existing checkout
13 | if [ ! -d "l10n-repo" ]; then
14 | git clone https://github.com/mozilla-l10n/scryer-android-l10n.git l10n-repo
15 | else
16 | cd l10n-repo
17 | git fetch origin
18 | git reset --hard origin/master
19 | cd ..
20 | fi
21 |
22 | # Import and convert po files in L10N repository to Android strings.xml files
23 | python tools/l10n/android2po/a2po.py import || echo "Could not import all locales"
24 |
25 | # a2po creates wrong folder names for locales with country (e.g. values-es-MX). Rename
26 | # those so that Android can find them (e.g. values-es-rMX)
27 | tools/l10n/fix_locale_folders.sh
28 |
29 | python tools/l10n/check_translations.py
30 |
--------------------------------------------------------------------------------