binwiederhier / ntfy-android

Android app for ntfy.sh
Apache License 2.0
465 stars 92 forks source link

Material Design 3 migration #56

Open Bnyro opened 1 year ago

Bnyro commented 1 year ago

Hey, this PR migrates the app to Material Design 3 since that's the new design standard. On Android 12 and up, dynamic accent colors will be used automatically (based on the wallpaper). If there are any suggestions for improvements, I'm open for adjusting these. Cheers

binwiederhier commented 1 year ago

Thank you for your PR. I will test/merge when I work on the Android app next; or maybe @wunter8 will get to it before me :-)

binwiederhier commented 1 year ago

I was finally looking at this. It is a little rough. I'm gonna look into this a little bit, but if you happen to feel like helping out again, I'd be more than happy to accept your help.

Light mode:

image

image

Dark mode looks okay-ish:

image

image

binwiederhier commented 1 year ago

This includes the latest main: https://github.com/binwiederhier/ntfy-android/pull/59

Bnyro commented 1 year ago

Wouldn't it make more sense if you just merged the main branch into my PR's branch instead of opening a new PR? That way I'd still be able to push changes (and you too because maintainers can push commits to PRs), because I don't have any write privileges on your PR.

Bnyro commented 1 year ago

I can look into the issues with the light mode later, I forgot to test the light mode when working on the PR.

binwiederhier commented 1 year ago

Awesome thanks. You can just pull in my changes and update your PR. I don't think I can update your PR either.

Bnyro commented 1 year ago

You can in fact, run git push git@github.com:Bnyro/ntfy-android.git HEAD:md3-migration

Bnyro commented 1 year ago

(I merged the changes from your PR into this branch now)

Bnyro commented 1 year ago

I fixed the issues with the status bar and top app bar I found, and we now use a theme generated by the material theme builder on Android 11 and below (see https://m3.material.io/theme-builder#/custom). The primary color used for the theme builder is the primary color of the current theme, so it should look similar to the current colors.

binwiederhier commented 1 year ago

@Bnyro Sorry for not reacting quicker. I am avoiding Android development a little :-)

I tried your branch and it's panicking with this stack trace:


05/20 14:16:26: Launching 'app' on Pixel 6 API 33.
Install successfully finished in 1 s 549 ms.
$ adb shell am start -n "io.heckel.ntfy/io.heckel.ntfy.ui.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 6130 on device 'Pixel_6_API_33 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/io.heckel.ntfy: Late-enabling -Xcheck:jni
W/io.heckel.ntfy: Unexpected CPU variant for x86: x86_64.
    Known variants: atom, sandybridge, silvermont, kabylake, default
W/re-initialized>: type=1400 audit(0.0:42): avc: granted { execute } for path="/data/data/io.heckel.ntfy/code_cache/startup_agents/8f49cff1-agent.so" dev="dm-33" ino=147527 scontext=u:r:untrusted_app:s0:c159,c256,c512,c768 tcontext=u:object_r:app_data_file:s0:c159,c256,c512,c768 tclass=file app=io.heckel.ntfy
V/studio.deploy: Startup agent attached to VM
V/studio.deploy: No existing instrumentation found. Loading instrumentation from instruments-b5380c1f.jar
W/io.heckel.ntfy: DexFile /data/data/io.heckel.ntfy/code_cache/.studio/instruments-b5380c1f.jar is in boot class path but is not in a known location
V/studio.deploy: Applying transforms with cached classes
W/io.heckel.ntfy: Redefining intrinsic method java.lang.Thread java.lang.Thread.currentThread(). This may cause the unexpected use of the original definition of java.lang.Thread java.lang.Thread.currentThread()in methods that have already been compiled.
W/io.heckel.ntfy: Redefining intrinsic method boolean java.lang.Thread.interrupted(). This may cause the unexpected use of the original definition of boolean java.lang.Thread.interrupted()in methods that have already been compiled.
D/CompatibilityChangeReporter: Compat change id reported: 171979766; UID 10159; state: ENABLED
D/nativeloader: Configuring classloader-namespace for other apk /system_ext/framework/androidx.window.extensions.jar. target_sdk_version=33, uses_libraries=ALL, library_path=/data/app/~~InpLG4Af31QJxCb3YuHUjw==/io.heckel.ntfy-fvmOhHRo_qBFWsGwvT16lQ==/lib/x86_64, permitted_path=/data:/mnt/expand:/data/user/0/io.heckel.ntfy
D/nativeloader: Configuring classloader-namespace for other apk /system_ext/framework/androidx.window.sidecar.jar. target_sdk_version=33, uses_libraries=ALL, library_path=/data/app/~~InpLG4Af31QJxCb3YuHUjw==/io.heckel.ntfy-fvmOhHRo_qBFWsGwvT16lQ==/lib/x86_64, permitted_path=/data:/mnt/expand:/data/user/0/io.heckel.ntfy
W/ziparchive: Unable to open '/data/app/~~InpLG4Af31QJxCb3YuHUjw==/io.heckel.ntfy-fvmOhHRo_qBFWsGwvT16lQ==/base.dm': No such file or directory
W/ziparchive: Unable to open '/data/app/~~InpLG4Af31QJxCb3YuHUjw==/io.heckel.ntfy-fvmOhHRo_qBFWsGwvT16lQ==/base.dm': No such file or directory
D/nativeloader: Configuring classloader-namespace for other apk /data/app/~~InpLG4Af31QJxCb3YuHUjw==/io.heckel.ntfy-fvmOhHRo_qBFWsGwvT16lQ==/base.apk. target_sdk_version=33, uses_libraries=, library_path=/data/app/~~InpLG4Af31QJxCb3YuHUjw==/io.heckel.ntfy-fvmOhHRo_qBFWsGwvT16lQ==/lib/x86_64, permitted_path=/data:/mnt/expand:/data/user/0/io.heckel.ntfy
V/GraphicsEnvironment: ANGLE Developer option for 'io.heckel.ntfy' set to: 'default'
V/GraphicsEnvironment: ANGLE GameManagerService for io.heckel.ntfy: false
V/GraphicsEnvironment: Neither updatable production driver nor prerelease driver is supported.
D/NetworkSecurityConfig: Using Network Security Config from resource network_security_config debugBuild: true
D/NetworkSecurityConfig: Using Network Security Config from resource network_security_config debugBuild: true
D/CompatibilityChangeReporter: Compat change id reported: 183155436; UID 10159; state: ENABLED
I/FirebaseApp: Device unlocked: initializing all Firebase APIs for app [DEFAULT]
I/FirebaseInitProvider: FirebaseApp initialization successful
D/WM-WrkMgrInitializer: Initializing WorkManager with default configuration.
D/libEGL: loaded /vendor/lib64/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib64/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib64/egl/libGLESv2_emulation.so
D/CompatibilityChangeReporter: Compat change id reported: 160794467; UID 10159; state: ENABLED
D/CompatibilityChangeReporter: Compat change id reported: 194532703; UID 10159; state: ENABLED
D/AppCompatDelegate: Checking for metadata for AppLocalesMetadataHolderService : Service not found
W/io.heckel.ntfy: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (unsupported, reflection, allowed)
W/io.heckel.ntfy: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (unsupported, reflection, allowed)
D/CompatibilityChangeReporter: Compat change id reported: 210923482; UID 10159; state: ENABLED
D/NtfyMainActivity: Create io.heckel.ntfy.ui.MainActivity@dcef83b
D/NtfyRepository: Created io.heckel.ntfy.db.Repository@aa40a3e
I/ActivityThread: Schedule relaunch activity: io.heckel.ntfy.ui.MainActivity
D/NtfyMainActivity: Poll worker version matches: choosing KEEP as existing work policy
D/NtfyMainActivity: Poll worker: Scheduling period work every 60 minutes
D/NtfyMainActivity: ServiceStartWorker version matches: choosing KEEP as existing work policy
D/NtfyMainActivity: ServiceStartWorker: Scheduling period work every 180 minutes
D/NtfyMainActivity: Delete worker version matches: choosing KEEP as existing work policy
D/NtfyMainActivity: Delete worker: Scheduling period work every 480 minutes
I/ActivityThread: Schedule relaunch activity: io.heckel.ntfy.ui.MainActivity
D/NtfyMainActivity: Battery: ignoring optimizations = true (we want this to be true); instant subscriptions = false; remind time reached = true; banner = false
I/Choreographer: Skipped 75 frames!  The application may be doing too much work on its main thread.
D/HostConnection: createUnique: call
D/HostConnection: HostConnection::get() New Host Connection established 0x7c4547181ad0, tid 6306
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_vulkan_queue_submit_with_commands ANDROID_EMU_sync_buffer_data ANDROID_EMU_vulkan_async_qsri ANDROID_EMU_read_color_buffer_dma ANDROID_EMU_hwc_multi_configs GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_1 
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
W/OpenGLRenderer: Failed to initialize 101010-2 format, error = EGL_SUCCESS
D/EGL_emulation: eglCreateContext: 0x7c454717fb50: maj 3 min 1 rcv 4
D/EGL_emulation: eglMakeCurrent: 0x7c454717fb50: ver 3 1 (tinfo 0x7c476ca01080) (first time)
I/Gralloc4: mapper 4.x is not supported
D/HostConnection: createUnique: call
D/HostConnection: HostConnection::get() New Host Connection established 0x7c4547180990, tid 6306
D/goldfish-address-space: allocate: Ask for block of size 0x100
D/goldfish-address-space: allocate: ioctl allocate returned offset 0x3efffe000 size 0x2000
W/Gralloc4: allocator 4.x is not supported
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_vulkan_queue_submit_with_commands ANDROID_EMU_sync_buffer_data ANDROID_EMU_vulkan_async_qsri ANDROID_EMU_read_color_buffer_dma ANDROID_EMU_hwc_multi_configs GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_1 
I/OpenGLRenderer: Davey! duration=1670ms; Flags=1, FrameTimelineVsyncId=158758, IntendedVsync=66472646931412, Vsync=66473896931362, InputEventId=0, HandleInputStart=66473909057066, AnimationStart=66473909062233, PerformTraversalsStart=66473909239250, DrawStart=66474217185930, FrameDeadline=66472663598078, FrameInterval=66473908884247, FrameStartTime=16666666, SyncQueued=66474248616654, SyncStart=66474262202228, IssueDrawCommandsStart=66474264069449, SwapBuffers=66474310829448, FrameCompleted=66474330636296, DequeueBufferDuration=7531, QueueBufferDuration=1656852, GpuCompleted=66474330636296, SwapBuffersCompleted=66474324085163, DisplayPresentTime=0, CommandSubmissionCompleted=66474310829448, 
W/Parcel: Expecting binder but got null!
D/NtfyMainActivity: Create io.heckel.ntfy.ui.MainActivity@3f8af5b
D/NtfyMainActivity: Poll worker version matches: choosing KEEP as existing work policy
D/NtfyMainActivity: Poll worker: Scheduling period work every 60 minutes
D/NtfyMainActivity: ServiceStartWorker version matches: choosing KEEP as existing work policy
D/NtfyMainActivity: ServiceStartWorker: Scheduling period work every 180 minutes
D/NtfyMainActivity: Delete worker version matches: choosing KEEP as existing work policy
D/NtfyMainActivity: Delete worker: Scheduling period work every 480 minutes
D/NtfyMainActivity: Battery: ignoring optimizations = true (we want this to be true); instant subscriptions = false; remind time reached = true; banner = false
I/Choreographer: Skipped 46 frames!  The application may be doing too much work on its main thread.
I/io.heckel.ntfy: Compiler allocated 4160KB to compile void android.widget.TextView.<init>(android.content.Context, android.util.AttributeSet, int, int)
W/Parcel: Expecting binder but got null!
I/OpenGLRenderer: Davey! duration=875ms; Flags=1, FrameTimelineVsyncId=159708, IntendedVsync=66473913598028, Vsync=66474680264664, InputEventId=0, HandleInputStart=66474695581226, AnimationStart=66474695584442, PerformTraversalsStart=66474695789900, DrawStart=66474743649993, FrameDeadline=66473930264694, FrameInterval=66474695422017, FrameStartTime=16666666, SyncQueued=66474765389174, SyncStart=66474769074835, IssueDrawCommandsStart=66474769262080, SwapBuffers=66474786150582, FrameCompleted=66474792880743, DequeueBufferDuration=8536, QueueBufferDuration=1127648, GpuCompleted=66474792749807, SwapBuffersCompleted=66474792880743, DisplayPresentTime=136640479362053, CommandSubmissionCompleted=66474786150582, 
D/NtfyPollWorker: Polling for new notifications
D/NtfyMainActivity: Checking global and subscription-specific 'muted until' timestamp
D/NtfyMainActivity: Battery: ignoring optimizations = true (we want this to be true); instant subscriptions = true; remind time reached = true; banner = false
D/NtfySubscriberMgr: Enqueuing work to refresh subscriber service
D/NtfyFirebase: Subscribing to topic ~control complete: result=null, exception=null, successful=true
D/NtfyApiService: Polling topic https://ntfy.sh/stats-internal/json?poll=1&since=K3QkhtzfI8z5
D/TrafficStats: tagSocket(115) with statsTag=0xffffffff, statsUid=-1
D/NtfySubscriberMgr: ServiceStartWorker: Starting foreground service with action START (work ID: 0f9561e0-46d7-4329-9346-b98bfea81477)
D/NtfySubscriberService: Subscriber service has been created
E/io.heckel.ntfy: Invalid ID 0xff00ff00.
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: io.heckel.ntfy, PID: 6130
    java.lang.RuntimeException: Unable to create service io.heckel.ntfy.service.SubscriberService: android.content.res.Resources$NotFoundException: Resource ID #0xff00ff00
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:4498)
        at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2161)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7872)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
     Caused by: android.content.res.Resources$NotFoundException: Resource ID #0xff00ff00
        at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:226)
        at android.content.res.Resources.getColor(Resources.java:1068)
        at android.content.Context.getColor(Context.java:794)
        at androidx.core.content.ContextCompat$Api23Impl.getColor(ContextCompat.java:1034)
        at androidx.core.content.ContextCompat.getColor(ContextCompat.java:578)
        at io.heckel.ntfy.service.SubscriberService.createNotification(SubscriberService.kt:294)
        at io.heckel.ntfy.service.SubscriberService.onCreate(SubscriberService.kt:99)
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:4485)
        at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2161) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loopOnce(Looper.java:201) 
        at android.os.Looper.loop(Looper.java:288) 
        at android.app.ActivityThread.main(ActivityThread.java:7872) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) 
I/WM-WorkerWrapper: Worker result SUCCESS for Work [ id=0f9561e0-46d7-4329-9346-b98bfea81477, tags={ io.heckel.ntfy.service.SubscriberServiceManager$ServiceStartWorker } ]
I/Process: Sending signal. PID: 6130 SIG: 9

I am looking into it now, but I figured maybe you had an idea already.

Bnyro commented 1 year ago

Oh yes, I know what's going on, my bad!

Bnyro commented 1 year ago

We can fix this by just removing ContextCompat.getColor(color) and replacing it with color where the notification icon color is set.

binwiederhier commented 1 year ago

Do you wanna join the Discord/Matrix to make this convo easier?

Bnyro commented 1 year ago

I could push the change tomorrow, probably in the evening, or I'll just let you do it and see whether you are able tp push to my branch ;)

Bnyro commented 4 months ago

Hey @binwiederhier , may we continue with this in the next time?

binwiederhier commented 4 months ago

Funny timing. I plan to work on the Android app tomorrow. I took the day off at work. Though I do think I will do the QR code and markdown tickets first. But I'll definitely address this afterwards.

codenyte commented 3 months ago

Any updates?

binwiederhier commented 3 months ago

Well, I started to do some Android work this weekend. Sorry everything takes so long

codenyte commented 3 months ago

Well, I started to do some Android work this weekend.

That's awesome.

Sorry everything takes so long

It's fine, I just wanted to know if anything was happening because the last comment in this thread is a month old.

DanH42 commented 1 month ago

Are there any plans to make this new theme optionally selectable by the user once it lands in a stable release? All my Android devices are on 11 or older, so apps using a Material You style theme stick out like a broken thumb and I'll typically avoid them if there's a more normal-looking alternative available (one of several reasons I've avoided moving any devices to 12+, where that's no longer possible).

I'll admit that the handful of screenshots from last May don't look nearly as nauseating as most Material You designs I've come across, so I'm hopeful that this may manage to be the first inoffensive implementation I've ever seen, but there's a lot that's not visible in those images. For a much stronger example, the landing page for the M3 theme builder linked above is pretty representative of the sort of "aggressively bland" Material You design that makes my head hurt just to look at, which of course makes me even more concerned that that's apparently how the colors for devices running Android 11 and older were selected.

I'd also point to an earlier comment on a related issue (https://github.com/binwiederhier/ntfy/issues/580#issuecomment-2081590133) describing some other undesirable changes that Material You-based designs typically bring with them, and I share in that user's hope that those particular changes in design language won't come to ntfy.