Skip to content

Commit 4e9c868

Browse files
committed
feat: recommend introduction video on first start (#16)
1 parent 6207db9 commit 4e9c868

File tree

4 files changed

+152
-1
lines changed

4 files changed

+152
-1
lines changed

app/src/main/kotlin/de/cyb3rko/pincredible/MainActivity.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import androidx.viewbinding.ViewBinding
2222
import com.google.android.material.appbar.MaterialToolbar
2323
import de.cyb3rko.backpack.activities.BackpackMainActivity
2424
import de.cyb3rko.backpack.interfaces.BackpackMain
25+
import de.cyb3rko.backpack.utils.Safe
2526
import de.cyb3rko.pincredible.databinding.ActivityMainBinding
27+
import de.cyb3rko.pincredible.modals.IntroBottomSheet
2628

2729
class MainActivity : BackpackMainActivity(), BackpackMain {
2830
private lateinit var binding: ActivityMainBinding
@@ -32,6 +34,10 @@ class MainActivity : BackpackMainActivity(), BackpackMain {
3234
binding = ActivityMainBinding.inflate(layoutInflater).asContentView()
3335
findNavController(R.id.nav_host_fragment_content_main).apply()
3436
bindInterface(this)
37+
38+
if (Safe.getBoolean(Safe.KEY_INTRO, true)) {
39+
IntroBottomSheet().show(supportFragmentManager, IntroBottomSheet.TAG)
40+
}
3541
}
3642

3743
override fun getBinding(): ViewBinding {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) 2025 Cyb3rKo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package de.cyb3rko.pincredible.modals
18+
19+
import android.content.ClipData
20+
import android.content.ClipboardManager
21+
import android.content.Context.CLIPBOARD_SERVICE
22+
import android.os.Bundle
23+
import android.view.LayoutInflater
24+
import android.view.View
25+
import android.view.ViewGroup
26+
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
27+
import de.cyb3rko.backpack.utils.Safe
28+
import de.cyb3rko.backpack.utils.openUrl
29+
import de.cyb3rko.pincredible.R
30+
import de.cyb3rko.pincredible.databinding.BottomsheetIntroBinding
31+
32+
class IntroBottomSheet : BottomSheetDialogFragment() {
33+
override fun onCreateView(
34+
inflater: LayoutInflater,
35+
container: ViewGroup?,
36+
savedInstanceState: Bundle?
37+
): View {
38+
val binding = BottomsheetIntroBinding.inflate(inflater)
39+
binding.title.text = getString(R.string.bottomsheet_intro_title)
40+
binding.notice.text = getString(R.string.bottomsheet_intro_notice)
41+
binding.openButton.setOnClickListener {
42+
openUrl(getString(R.string.intro_link), LINK_LABEL)
43+
}
44+
binding.copyButton.setOnClickListener {
45+
val clipboard = this.activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?
46+
if (clipboard == null) return@setOnClickListener
47+
clipboard.setPrimaryClip(
48+
ClipData.newPlainText(LINK_LABEL, getString(R.string.intro_link))
49+
)
50+
}
51+
Safe.writeBoolean(Safe.KEY_INTRO, false)
52+
return binding.root
53+
}
54+
55+
companion object {
56+
const val TAG = "Notice Bottom Sheet"
57+
private const val LINK_LABEL = "Introduction YouTube video"
58+
}
59+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<!--
4+
~ Copyright (c) 2023-2025 Cyb3rKo
5+
~
6+
~ Licensed under the Apache License, Version 2.0 (the "License");
7+
~ you may not use this file except in compliance with the License.
8+
~ You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing, software
13+
~ distributed under the License is distributed on an "AS IS" BASIS,
14+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
~ See the License for the specific language governing permissions and
16+
~ limitations under the License.
17+
-->
18+
19+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
20+
xmlns:app="http://schemas.android.com/apk/res-auto"
21+
android:layout_width="match_parent"
22+
android:layout_height="wrap_content"
23+
android:orientation="vertical"
24+
android:paddingStart="32dp"
25+
android:paddingTop="8dp"
26+
android:paddingEnd="32dp"
27+
android:paddingBottom="24dp">
28+
29+
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
30+
android:id="@+id/drag_handle"
31+
android:layout_width="match_parent"
32+
android:layout_height="wrap_content" />
33+
34+
<TextView
35+
android:id="@+id/title"
36+
android:layout_width="match_parent"
37+
android:layout_height="wrap_content"
38+
android:layout_marginBottom="16dp"
39+
android:gravity="center_horizontal"
40+
android:text="@string/bottomsheet_intro_title"
41+
android:textSize="22sp"
42+
android:textStyle="bold" />
43+
44+
<TextView
45+
android:id="@+id/notice"
46+
android:layout_width="match_parent"
47+
android:layout_height="wrap_content"
48+
android:gravity="center_horizontal"
49+
android:text="@string/bottomsheet_intro_notice"
50+
android:textSize="18sp" />
51+
52+
<LinearLayout
53+
android:layout_width="match_parent"
54+
android:layout_height="wrap_content"
55+
android:layout_marginTop="10dp"
56+
android:gravity="center_horizontal"
57+
android:orientation="horizontal">
58+
59+
<com.google.android.material.button.MaterialButton
60+
android:id="@+id/open_button"
61+
style="@style/Widget.Material3.Button.OutlinedButton"
62+
android:layout_width="wrap_content"
63+
android:layout_height="wrap_content"
64+
android:layout_gravity="center_horizontal"
65+
android:text="@string/bottomsheet_intro_open_button"
66+
app:icon="@android:drawable/ic_menu_set_as" />
67+
68+
<com.google.android.material.button.MaterialButton
69+
android:id="@+id/copy_button"
70+
style="@style/Widget.Material3.Button.OutlinedButton"
71+
android:layout_width="wrap_content"
72+
android:layout_height="wrap_content"
73+
android:layout_gravity="center_horizontal"
74+
android:layout_marginStart="6dp"
75+
android:text="@string/bottomsheet_intro_copy_button" />
76+
77+
</LinearLayout>
78+
79+
</LinearLayout>

app/src/main/res/values/strings.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<resources>
22
<string name="github_link" translatable="false">https://github.com/cyb3rko/pincredible</string>
3+
<string name="intro_link" translatable="false">https://youtube.com/shorts/0NE_BrUyQ5g</string>
34
<string name="settings">Settings</string>
45

56
<!-- Fragment Labels -->
@@ -51,6 +52,12 @@
5152
<string name="dialog_image_title">PIN table image</string>
5253
<string name="dialog_image_message">Are you sure?\n\nYou are about to save this unencrypted PIN table to %s.</string>
5354

55+
<!-- Bottomsheet content -->
56+
<string name="bottomsheet_intro_title">👋 Welcome to PINcredible 🔒</string>
57+
<string name="bottomsheet_intro_notice">If you use this app for the first time and want to know how to manage PINs with this app, you can watch the introduction video:</string>
58+
<string name="bottomsheet_intro_open_button">Open video</string>
59+
<string name="bottomsheet_intro_copy_button">Copy URL</string>
60+
5461
<!-- Toasts -->
5562
<string name="toast_stacktrace">Stracktrace copied</string>
5663

@@ -70,4 +77,4 @@
7077
<string name="dialog_restart_title">Restart required</string>
7178
<string name="dialog_restart_message">The change will be visible on next app start.\n\nDo you want to restart now?</string>
7279
<string name="dialog_restart_button2">Later</string>
73-
</resources>
80+
</resources>

0 commit comments

Comments
 (0)