work

Prompt

# ROLE You are a senior Android engineer (Kotlin, classic View system, custom drawing, spring animation). You have NO memory of earlier work and you cannot run code, so everything you need is in this message. Write code that compiles on the first try. Think carefully, then mentally compile every file (imports, types, nullability, API levels) before you output it. # GOAL Write "Milestone 1" of an Android launcher that looks and feels like the current iOS home screen. Nothing inside the launcher may look or move like stock Android (no ripples, no Material elevation shadows, no overscroll glow, no default Android transitions inside the launcher). Milestone 1 is a working skeleton that is also a measurement tool: it must let the owner measure frame times and test the app-open animation on the real phone. # TARGET DEVICE (the only device that matters) OPPO A5 2020 (CPH1933), ColorOS 11.1, Android 11 (API 30), Snapdragon 665 (Adreno 610), 4 GB RAM, 64 GB storage with little free space, screen about 720x1600. minSdk 30, targetSdk 30. It is a weak phone: 60 fps on this hardware is a hard requirement. The owner will measure it; you must never claim it is smooth. # HARD RULES 1. Use ONLY APIs that exist on API 30. Forbidden: RenderEffect, AGSL/RuntimeShader, predictive back, themed/monochrome icons (API 33), anything added after API 30, hidden or reflection APIs, Jetpack Compose, any library except the one listed below. Put a `// API n` comment on every framework call newer than API 21. 2. Kotlin, programmatic Views only. No XML layouts. The only resource files are the manifest, `themes.xml` and `strings.xml`. 3. Only one extra dependency: `androidx.dynamicanimation:dynamicanimation:1.1.0`. 4. Do not invent APIs, constants, versions or Apple facts. Use only the values in this message. If you need a number that is not given, define it as a named constant in `Tokens.kt` with the comment `// ASSUMPTION` and keep going. 5. No Apple assets (icons, SF fonts, wallpapers, sounds). Do not copy GPL code. Write everything yourself. Use the platform default sans-serif font for now (Inter is added later); do not use any font file. 6. Honesty: you cannot compile or run anything. Label the whole output UNTESTED and list the places most likely to fail (see OUTPUT FORMAT). Never write "this will be smooth" or "this works". 7. Do not build: lock screen, app lock, widgets, folders, drag and drop, wiggle mode, App Library, search. Those are later milestones. (Facts for later: a secure lock screen is impossible for a normal app; app lock inside a launcher is only a privacy aid.) # ONE-TIME SETUP THE OWNER WILL DO (print these steps first, short) Android Studio, New Project, "Empty Views Activity", Language Kotlin, Minimum SDK API 30, name "Ember Launcher", package `com.ember.launcher`. Then delete `MainActivity.kt`, `res/layout/activity_main.xml` and `res/values-night/themes.xml`, and replace/add the files you provide. Add the dependency line (give it for both Groovy `build.gradle` and Kotlin `build.gradle.kts`). Use `compileSdk` and `targetSdk` as the template provides, but set `targetSdk = 30` and `minSdk = 30`. # DESIGN DATA (use exactly; all of it goes into Tokens.kt) ## Colors (Apple system colors from Apple's official design data: light / dark) red #FF383C / #FF4245; orange #FF8D28 / #FF9230; yellow #FFCC00 / #FFD600; green #34C759 / #30D158; mint #00C8B3 / #00DAC3; teal #00C3D0 / #00D2E0; cyan #00C0E8 / #3CD3FE; blue #0088FF / #0091FF; indigo #6155F5 / #6D7CFF; purple #CB30E0 / #DB34F2; pink #FF2D55 / #FF375F; brown #AC7F5E / #B78A66; gray #8E8E93 / #8E8E93; gray2 #AEAEB2 / #636366; gray3 #C7C7CC / #48484A; gray4 #D1D1D6 / #3A3A3C; gray5 #E5E5EA / #2C2C2E; gray6 #F2F2F7 / #1C1C1E. Default accent: blue. Caveat: Apple's color page was last updated before the newest iOS release; these may be one version old. Launcher tokens (all ASSUMPTION): label color white; label shadow = black 30% alpha, drawn as a second text pass offset 1 dp (do not use setShadowLayer); glass tint light = white 18% alpha, dark = black 25% alpha; glass border = 1 dp vertical gradient white 35% alpha at top to white 5% at bottom; glass top highlight = 2 dp strip, white 50% alpha at top fading to 0; folder/search scrims are out of scope. Pick light or dark tokens from `Configuration.uiMode` night bit. ## Springs (Android SpringForce: stiffness, dampingRatio) Derived (ASSUMPTION) from Apple-style response r and dampingFraction z by stiffness = (2*pi/r)^2, dampingRatio = z. Define all in Tokens.kt, use only the four marked *. sp.press* 1754.6 / 0.85 (icon press scale) | sp.page* 322.3 / 1.00 (page snap) | sp.open* 195.0 / 0.90 (app open overlay progress) | sp.close* 246.7 / 1.00 (return to icon) | sp.drop 438.7 / 0.75 | sp.reflow 438.7 / 0.90 | sp.pop 631.7 / 0.70 | sp.fopen 195.0 / 0.85 | sp.fclose 322.3 / 1.00 | sp.stack 322.3 / 0.90 | sp.search 246.7 / 1.00 | sp.library 246.7 / 1.00 | sp.rubber 438.7 / 1.00. Rules: every animation is a spring, interruptible, retargeted with its current velocity (never restarted); a finger touching an animating element cancels its spring and takes control; on release the finger velocity is the spring's start velocity; a tap must respond immediately and never wait for an animation. ## Layout (all ASSUMPTION until calibrated on the phone) Scale factor s = screenWidthDp / 393. Icon edge 60 * s dp. Grid 4 columns x 6 rows per page, 4 dock slots. Icon corner radius = 22.37% of icon edge, continuous squircle curve (build one cubic-Bezier or superellipse Path per size, cache it; pre-mask icon bitmaps once at load; no per-frame clipping of icons). Label 12 * s sp, one line, centered, ellipsized, about 6 dp under the icon. Dock: wide rounded rectangle glass panel, 4 icons, floating above the bottom with a gap, respecting the bottom system inset. Page dots centered above the dock. ## Glass (fake, cheap, no real blur) Load the wallpaper once on a background thread (`WallpaperManager.getInstance(ctx).drawable`, needs READ_EXTERNAL_STORAGE on API 30; request it at runtime; if denied or null, fall back to a flat dark gradient). Center-crop to screen size, downscale to 1/4 scale, blur with a 3-pass box blur (radius about 6 px at that scale, ASSUMPTION), keep ONE blurred bitmap shared by all glass surfaces. A glass surface draws the part of that bitmap under its own screen rectangle (source rect to destination rect), clipped to its rounded shape, then tint fill, then 1 dp border gradient, then the 2 dp top highlight. No shadows in this milestone. Budget: at most 2 overdraw layers on the dock; extra glass memory under 1 MiB beyond the wallpaper bitmaps (sharp 720x1600 ARGB_8888 is about 4.39 MiB, blurred 180x400 is about 0.27 MiB). Show the sharp wallpaper behind the launcher with the window theme (`android:windowShowWallpaper`), so the sharp copy needs no extra bitmap. ## Icons Load apps with `LauncherApps.getActivityList(null, Process.myUserHandle())` (API 21) plus a `<queries>` block for `android.intent.action.MAIN` / `android.intent.category.LAUNCHER`. For each app: take `LauncherActivityInfo.getBadgedIcon(0)`; if it is an `AdaptiveIconDrawable` (API 26) draw background then foreground; otherwise draw the legacy icon onto a neutral plate; scale to the icon edge, mask with the squircle, add a thin rim (outer 1 px black 25% alpha, inner top 1 px white 35% alpha), store as ARGB_8888 in an LRU cache sized for about 80 icons. Decode off the main thread. Sort apps alphabetically for now. Fill the grid page by page; the first 4 apps by a fixed list of common package names (phone, messages, camera, browser) go to the dock if installed, otherwise the first 4 apps. Press feedback: scale to 0.92 with sp.press on touch down, back to 1.0 on up or cancel, carrying velocity. ## Paging Custom `PagerView` (not ViewPager): horizontal drag follows the finger, release picks the page from position and velocity (`VelocityTracker`), settles with a SpringAnimation (sp.page) on the container's translationX, interruptible mid-flight. Light haptic tick on snap: `VibrationEffect.createPredefined(EFFECT_TICK)` (API 29) via the system Vibrator (add VIBRATE permission), wrapped so unsupported hardware does nothing. ## App-open overlay (the key experiment) On icon tap: a full-screen overlay view draws a rounded rectangle filled with the icon's average color. One scalar progress 0..1 runs on sp.open; the rectangle is interpolated from the tapped icon's rect to the full screen, and its corner radius from the icon radius to 0. Start the target app with one of three modes, switchable at runtime from the HUD: - Mode A: `ActivityOptions.makeCustomAnimation(context, 0, 0)` (API 16; zero means no system animation). - Mode B: `ActivityOptions.makeClipRevealAnimation(view, 0, 0, view.width, view.height)` (API 23). - Mode C: plain `startActivity` with no options (control). When the launcher resumes after the user returns home, run the reverse with sp.close from full screen back to the icon, then hide the overlay. If the user taps again during the animation, retarget the same spring; never stack overlays. Note: the true system "icon morphs into the app window" effect is not possible for normal apps; this overlay is a substitute that the owner will measure. ## Measurement HUD (must be included) A small translucent overlay (top-left, tap to show/hide, long-press to cycle open mode A/B/C) driven by `Choreographer.FrameCallback`: rolling window of the last 120 frame intervals; show median ms, p95 ms, and janky % where a frame is janky if its interval exceeds 1.5 times (1000 / display refresh rate); show the refresh rate, the current open mode, and the process-start counter. Also `Log.d("EMBER_HUD", ...)` once per second while visible. Targets (for the owner to compare, not claims): p95 at most 16.67 ms, janky at most 5%. ## Default launcher and survival Manifest activity: `launchMode="singleTask"`, `exported="true"`, intent filter MAIN + HOME + DEFAULT, `stateNotNeeded`, `windowSoftInputMode="adjustPan"`. On first launch, if the app does not hold the home role, request it with `RoleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)` and `startActivityForResult` (API 29), with `Settings.ACTION_HOME_SETTINGS` as fallback. `Application` subclass increments a process-start counter in SharedPreferences and stores the timestamp (to show how often ColorOS kills the process). Handle back so the launcher never exits (return to page 0). Known ColorOS facts for the owner (community-level, unverified): the home-app setting is under Settings, App management, Default apps, Home app; the owner may need to enable auto-launch, allow background activity, and lock the app in the recents card. # OUTPUT FORMAT (follow exactly, in this order) 1. SETUP: the one-time steps above, as a numbered list, plus the dependency line for Groovy and for Kotlin DSL. 2. TEST PLAN (max 25 lines): how the owner installs, sets it as default, and runs these tests: (a) scroll pages fast and slow 20 times and read the HUD; (b) open 5 different apps in each of modes A, B and C and note by eye whether any frame shows a blank or flash; (c) reboot, leave the screen off 30 minutes, press Home 50 times, read the process-start counter; (d) exact adb commands for an independent check: `adb shell dumpsys gfxinfo com.ember.launcher reset`, perform the gesture, then `adb shell dumpsys gfxinfo com.ember.launcher framestats`, and `adb shell dumpsys meminfo com.ember.launcher`. Then a REPORT TEMPLATE the owner fills in and pastes back (HUD median/p95/jank per test, mode comparison notes, process-start counter, anything that crashed). 3. FILES: each file under a heading with its full path, in its own fenced code block, complete (never partial). Order: `AndroidManifest.xml`, `res/values/themes.xml`, `res/values/strings.xml`, `Tokens.kt`, `SquircleShape.kt`, `WallpaperGlass.kt`, `GlassPanel.kt`, `IconRepository.kt`, `IconView.kt`, `CellGridLayout.kt`, `PagerView.kt`, `DockView.kt`, `OpenAnimator.kt`, `FrameHud.kt`, `EmberApp.kt`, `LauncherActivity.kt`. Package `com.ember.launcher`. Keep the total under about 1,200 lines of Kotlin. Prefer simple, correct code over clever code. 4. COMPILE RISK LIST (max 10 lines): the places most likely to fail to compile or crash, and what the owner should paste back if they do. 5. Final line: `END OF FILES` (so the owner can see the output was not cut off). If you cannot fit everything, never cut a file in half: stop at a file boundary and print `TRUNCATED AFTER <file>`. Drop things in this order and say what you dropped: haptics, light-mode tokens, the blur (use a flat tint instead), mode B. Never drop: manifest, grid, pager, icon pipeline, dock glass, HUD, open overlay. Begin now with the SETUP section.

Response not available

Drag to resize