Initial commit

This commit is contained in:
2026-05-10 10:45:02 +08:00
commit e62384a9c5
1053 changed files with 19615 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
*.apk
*.aab
*.keystore
keystore.properties

150
README.md Normal file
View File

@@ -0,0 +1,150 @@
# Hoops — Android
一個籃球小遊戲的 Android 包裝。遊戲本體是純 HTML5 Canvas這個 app 就是一層全螢幕 WebView 殼。
## 為什麼這樣做
- **沒有網路權限** — 遊戲完全離線,所有資源都打包在 `assets/` 裡。
- **沒有第三方追蹤** — 沒有 Google Play Services、沒有 Analytics、沒有任何網路請求。
- **沒有自定義 Activity 之外的東西** — 整個 app 就一個 `MainActivity.kt`,七十幾行。
- **F-Droid 友好** — 純開源、無 proprietary 依賴、無外部資源。
## 專案結構
```
hoops-android/
├── app/
│ ├── build.gradle.kts
│ └── src/main/
│ ├── AndroidManifest.xml
│ ├── java/blog/wiwi/hoops/MainActivity.kt
│ ├── assets/index.html ← 整個遊戲在這裡
│ └── res/ ← icon、主題、字串
├── build.gradle.kts
├── settings.gradle.kts
└── gradle.properties
```
**最重要的是 `app/src/main/assets/index.html`**——這是整個遊戲。要改遊戲邏輯,改這個檔案就好,其他 Android 殼層的東西完全不用碰。
## 怎麼建置
### 第一次
1. 安裝 [Android Studio](https://developer.android.com/studio)(或裝 command-line 的 Android SDK
2. 用 Android Studio 開啟 `hoops-android` 資料夾
3. 等 Gradle sync 完(第一次會下載一些東西)
4. **產生 Gradle wrapper**——在專案根目錄跑:
```bash
gradle wrapper --gradle-version 8.7
```
或在 Android Studio 裡點 `File → Sync Project with Gradle Files`,它會自己生成 `gradlew`、`gradlew.bat`、`gradle/wrapper/gradle-wrapper.jar`。
### 建置 debug APK測試用
```bash
./gradlew assembleDebug
```
APK 會在 `app/build/outputs/apk/debug/app-debug.apk`,可以直接 adb install 到手機。
### 建置 release APK要簽章
先產生 keystore
```bash
keytool -genkey -v -keystore hoops-release.keystore \
-alias hoops -keyalg RSA -keysize 2048 -validity 10000
```
建一個 `keystore.properties`**不要 commit 到 git**
```properties
storeFile=../hoops-release.keystore
storePassword=你的密碼
keyAlias=hoops
keyPassword=你的密碼
```
修改 `app/build.gradle.kts`,加上 signing config看註解的位置。然後
```bash
./gradlew assembleRelease
```
## 怎麼測
### 在電腦上先測網頁版
直接在瀏覽器打開 `app/src/main/assets/index.html`——它就是個獨立的 HTML 檔,可以直接跑。
這是改遊戲邏輯時最快的迭代方式。
### 用 Android emulator 測
1. Android Studio → Device Manager → 建一個 Pixel 5 之類的 emulator
2. 點綠色 ▶ 跑
### 用實機測
1. 手機開「開發人員選項」→「USB 偵錯」
2. USB 接電腦
3. Android Studio 應該會看到裝置
4. 點 ▶ 跑
## 上 F-Droid 的注意事項
F-Droid 會自己從你的 git repo 建置 APK所以
1. **把整個專案推到公開 git repo**GitHub、Codeberg 都行)
2. **打 git tag** 標版本,例如 `v1.0.0`
3. **送 metadata PR** 到 [fdroiddata](https://gitlab.com/fdroid/fdroiddata),告訴 F-Droid 怎麼建置你的 app
metadata yml 大致長這樣:
```yaml
Categories:
- Games
License: MIT # 或你選的授權
SourceCode: https://github.com/你/hoops-android
IssueTracker: https://github.com/你/hoops-android/issues
AutoName: Hoops
RepoType: git
Repo: https://github.com/你/hoops-android.git
Builds:
- versionName: 1.0.0
versionCode: 1
commit: v1.0.0
subdir: app
gradle:
- yes
AutoUpdateMode: Version
UpdateCheckMode: Tags
CurrentVersion: 1.0.0
CurrentVersionCode: 1
```
完整文件:<https://f-droid.org/docs/Submitting_to_F-Droid_Quick_Start_Guide/>
### F-Droid 會檢查的東西
- ❌ 不能依賴 Google Play Services / Firebase
- ❌ 不能有 proprietary 二進位依賴
- ❌ 不能呼叫追蹤服務Analytics、Crashlytics 等)
- ✅ 純 OSS 依賴
- ✅ 從原始碼可重現建置
這個專案天生就符合所有條件——只用 androidx沒有任何 proprietary 東西。
## 常見問題
**Q: 為什麼不直接做成 PWA**
A: PWA 也是個好方案,但要上 F-Droid 必須是真正的 Android app。
**Q: 改了 `index.html` 怎麼快速看效果?**
A: 雙擊用瀏覽器開那個檔案,直接玩。要看 Android 上的效果再 build。
**Q: APK 大概多大?**
A: 約 24 MB。幾乎全部是 androidx 的 Kotlin 標準庫。`assets/index.html` 本身不到 30 KB。
**Q: 想加新遊戲模式怎麼辦?**
A: 改 `index.html`,重 build。Kotlin 那邊永遠不需要改。

53
app/build.gradle.kts Normal file
View File

@@ -0,0 +1,53 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "blog.wiwi.hoops"
compileSdk = 34
defaultConfig {
applicationId = "blog.wiwi.hoops"
minSdk = 24 // Android 7.0+ 才有體面的 WebView 跟 Pointer Events
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
}
buildTypes {
release {
isMinifyEnabled = false
// 不用 proguard這個 app 程式碼太少,混淆只會徒增 F-Droid 審核難度
signingConfig = signingConfigs.getByName("debug") // 自己 sign 時請改
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
// 排除一些不必要的東西,把 APK 壓到最小
packaging {
resources {
excludes += setOf(
"META-INF/*.kotlin_module",
"META-INF/AL2.0",
"META-INF/LGPL2.1",
"kotlin-tooling-metadata.json"
)
}
}
}
dependencies {
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.activity:activity:1.9.0")
// Splash Screen APIAndroid 12+ 是系統 splash舊版會被 backport
implementation("androidx.core:core-splashscreen:1.0.1")
}

View File

@@ -0,0 +1,21 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "blog.wiwi.hoops",
"variantName": "debug",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0.0",
"outputFile": "app-debug.apk"
}
],
"elementType": "File",
"minSdkVersionForDexing": 24
}

View File

@@ -0,0 +1,2 @@
#- File Locator -
listingFile=../../../../outputs/apk/debug/output-metadata.json

View File

@@ -0,0 +1,2 @@
#- File Locator -
listingFile=../../../../outputs/apk/androidTest/debug/output-metadata.json

View File

@@ -0,0 +1,2 @@
#- File Locator -
listingFile=../../../../../release/output-metadata.json

View File

@@ -0,0 +1,2 @@
appMetadataVersion=1.1
androidGradlePluginVersion=8.13.2

View File

@@ -0,0 +1,2 @@
appMetadataVersion=1.1
androidGradlePluginVersion=8.13.2

View File

@@ -0,0 +1,881 @@
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>Hoops</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body {
width: 100%; height: 100%;
background: #fafaf7;
overflow: hidden;
overscroll-behavior: none;
user-select: none; -webkit-user-select: none;
touch-action: none;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
#stage {
position: fixed; inset: 0;
display: flex; align-items: center; justify-content: center;
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
#wrap {
position: relative;
/* 取畫面上能擺進的最大正方形 */
width: min(100vw, 100vh);
height: min(100vw, 100vh);
}
canvas {
display: block;
width: 100%; height: 100%;
background: #fafaf7;
touch-action: none;
}
.hint {
position: absolute;
left: 50%; bottom: 8px;
transform: translateX(-50%);
font-size: 5px;
letter-spacing: 0.01em;
opacity: 0.45;
color: #555;
white-space: nowrap;
pointer-events: none;
}
</style>
</head>
<body>
<div id="stage">
<div id="wrap">
<canvas id="game"></canvas>
<div class="hint">by Wiwi Kuan, https://wiwi.blog</div>
</div>
</div>
<script>
// =============================================================================
// CONFIG — 跟原本完全一樣
// =============================================================================
const DEFAULT_CONFIG = {
GAME_DURATION: 60,
COOLDOWN: 0.5,
JUMP_DURATION: 0.5,
JUMP_HEIGHT_RATIO: 0.25,
PERFECT_WINDOW_T: 0.28,
PERFECT_TOLERANCE: 0.001,
MAX_DRIFT_T: 0.35,
GRAVITY_RATIO: 5,
BALL_RADIUS_RATIO: 0.03,
RESTITUTION_RIM: 0.65,
RESTITUTION_BOARD: 0.7,
RESTITUTION_BALL: 0.7,
AIR_DRAG: 0,
SHOT_TARGET_TIME: 0.75,
SHOT_DRIFT_VEL: 0.4,
SHOT_DRIFT_ANGLE: 0.6,
BALL_IMG_SRC: null,
PERFECT_JITTER_VEL: 0.0025,
PERFECT_JITTER_ANGLE: 0.003,
EULER_COMPENSATION: 0.012,
};
const COLORS = {
ink: '#1a1a1a',
paper: '#fafaf7',
ball: '#c2410c',
rim: '#991b1b',
net: '#999',
gray: '#ccc',
};
const PHASE = { TITLE: 'title', PLAYING: 'playing', OVER: 'over' };
const MODE = { TIMED: 'timed', PRACTICE: 'practice' };
// =============================================================================
// 遊戲主體 — 接收 canvas + config,回傳 cleanup function
// 注意:原本是用 parent.clientWidth 取尺寸,這裡改成 wrap 元素的尺寸(其實一樣)
// 並且讓畫布是「正方形 = min(視窗寬, 視窗高)」,跟原本邏輯一致
// =============================================================================
function initGame(canvas, userConfig) {
const CONFIG = Object.assign({}, DEFAULT_CONFIG, userConfig || {});
const ctx = canvas.getContext('2d');
let W = 0, H = 0, DPR = 1;
function resize() {
const parent = canvas.parentElement;
const parentW = parent ? parent.clientWidth : 600;
const parentH = parent ? parent.clientHeight : 600;
// 取較小邊作為正方形邊長
const px = Math.max(280, Math.floor(Math.min(parentW, parentH)));
DPR = Math.max(1, Math.min(2, window.devicePixelRatio || 1));
canvas.style.width = px + 'px';
canvas.style.height = px + 'px';
canvas.width = Math.floor(px * DPR);
canvas.height = Math.floor(px * DPR);
ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
W = px; H = px;
}
resize();
let ballImg = null;
if (CONFIG.BALL_IMG_SRC) {
const img = new Image();
img.onload = () => { ballImg = img; };
img.src = CONFIG.BALL_IMG_SRC;
}
// ===== Audio =====
let actx = null;
function audio() {
if (!actx) {
try { actx = new (window.AudioContext || window.webkitAudioContext)(); }
catch (e) { actx = null; }
}
return actx;
}
function blip({ freq = 440, dur = 0.08, type = 'sine', vol = 0.15, sweep = 0, delay = 0 } = {}) {
const a = audio(); if (!a) return;
const t0 = a.currentTime + delay;
const o = a.createOscillator();
const g = a.createGain();
o.type = type;
o.frequency.setValueAtTime(freq, t0);
if (sweep) o.frequency.exponentialRampToValueAtTime(Math.max(40, freq + sweep), t0 + dur);
g.gain.setValueAtTime(0.0001, t0);
g.gain.exponentialRampToValueAtTime(vol, t0 + 0.005);
g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
o.connect(g).connect(a.destination);
o.start(t0); o.stop(t0 + dur + 0.02);
}
const SFX = {
jump: () => blip({ freq: 220, dur: 0.06, type: 'triangle', vol: 0.08, sweep: 60 }),
shoot: () => blip({ freq: 380, dur: 0.09, type: 'square', vol: 0.07, sweep: 200 }),
rim: () => blip({ freq: 900, dur: 0.05, type: 'square', vol: 0.06, sweep: -300 }),
board: () => blip({ freq: 140, dur: 0.07, type: 'sine', vol: 0.12, sweep: -40 }),
swish: () => {
blip({ freq: 660, dur: 0.08, type: 'sine', vol: 0.10 });
blip({ freq: 990, dur: 0.10, type: 'sine', vol: 0.08, delay: 0.04 });
blip({ freq: 1320, dur: 0.12, type: 'sine', vol: 0.06, delay: 0.09 });
},
score: () => {
blip({ freq: 523, dur: 0.10, type: 'triangle', vol: 0.10 });
blip({ freq: 784, dur: 0.14, type: 'triangle', vol: 0.10, delay: 0.08 });
},
end: () => {
blip({ freq: 220, dur: 0.18, type: 'sawtooth', vol: 0.08 });
blip({ freq: 165, dur: 0.22, type: 'sawtooth', vol: 0.08, delay: 0.12 });
},
};
function geom() {
const hoopX = W * 0.78;
const hoopW = W * 0.085;
const rimR = W * 0.008;
const armLength = W * 0.018;
return {
ballR: W * CONFIG.BALL_RADIUS_RATIO,
ballX: W * 0.18,
groundY: H * 0.72,
hoopX, hoopY: H * 0.42, hoopW, rimR, armLength,
boardX: hoopX + hoopW / 2 + rimR + armLength,
boardTop: H * 0.42 - H * 0.18,
boardBot: H * 0.42 + H * 0.04,
netDepth: H * 0.06,
};
}
const state = {
phase: PHASE.TITLE,
mode: MODE.TIMED,
timeLeft: CONFIG.GAME_DURATION,
score: 0,
attempts: 0,
lastScoreFlash: 0,
holding: false,
holdT: 0,
holdStartTime: 0,
jumpDone: false,
cooldown: 0,
ready: true,
balls: [],
netPhase: 0,
netImpulse: 0,
nextBallId: 1,
};
// 給想作弊的讀者
if (typeof window !== 'undefined') window.__hoops = { state, CONFIG };
let titleButtons = null;
let exitButton = null;
function startGame(mode) {
state.phase = PHASE.PLAYING;
state.mode = mode;
state.timeLeft = CONFIG.GAME_DURATION;
state.score = 0;
state.attempts = 0;
state.lastScoreFlash = 0;
state.holding = false;
state.holdT = 0;
state.holdStartTime = 0;
state.jumpDone = false;
state.cooldown = 0;
state.ready = true;
state.balls = [];
state.netImpulse = 0;
}
function backToTitle() {
state.phase = PHASE.TITLE;
state.holding = false;
state.jumpDone = false;
state.balls = [];
}
function pressDown(pointerPos) {
audio();
if (state.phase === PHASE.OVER) {
backToTitle();
return;
}
if (state.phase === PHASE.TITLE) {
if (pointerPos && titleButtons) {
const { x, y } = pointerPos;
const inBtn = (b) => x >= b.x && x <= b.x + b.w && y >= b.y && y <= b.y + b.h;
if (inBtn(titleButtons.timed)) { startGame(MODE.TIMED); return; }
if (inBtn(titleButtons.practice)) { startGame(MODE.PRACTICE); return; }
}
return;
}
if (state.mode === MODE.PRACTICE && pointerPos && exitButton) {
const { x, y } = pointerPos;
const b = exitButton;
if (x >= b.x && x <= b.x + b.w && y >= b.y && y <= b.y + b.h) {
backToTitle();
return;
}
}
if (!state.ready || state.holding) return;
state.holding = true;
state.holdT = 0;
state.holdStartTime = performance.now();
state.jumpDone = false;
SFX.jump();
}
function pressUp() {
if (!state.holding) return;
state.holding = false;
if (state.jumpDone) return;
const realHoldT = (performance.now() - state.holdStartTime) / 1000;
releaseShot(Math.min(realHoldT, CONFIG.JUMP_DURATION));
}
// ===== Event handlers =====
// App 內不需要擔心捲頁鍵盤事件保留給有實體鍵盤的裝置藍牙鍵盤、Chromebook
const isEditableTarget = (target) => {
if (!target) return false;
const tag = target.tagName || '';
return tag === 'INPUT' || tag === 'TEXTAREA' || target.isContentEditable;
};
const onKeyDown = (e) => {
if (isEditableTarget(e.target)) return;
if (state.phase === PHASE.TITLE) {
if (e.code === 'Digit1' || e.code === 'Numpad1') {
e.preventDefault(); if (e.repeat) return;
audio(); startGame(MODE.TIMED); return;
}
if (e.code === 'Digit2' || e.code === 'Numpad2') {
e.preventDefault(); if (e.repeat) return;
audio(); startGame(MODE.PRACTICE); return;
}
if (e.code === 'Space') e.preventDefault();
return;
}
if (state.phase === PHASE.OVER) {
if (e.code === 'Space') {
e.preventDefault(); if (e.repeat) return;
audio(); backToTitle();
}
return;
}
if (state.mode === MODE.PRACTICE && e.code === 'Escape') {
e.preventDefault(); if (e.repeat) return;
backToTitle(); return;
}
if (e.code !== 'Space') return;
e.preventDefault();
if (e.repeat) return;
pressDown();
};
const onKeyUp = (e) => {
if (e.code !== 'Space') return;
if (isEditableTarget(e.target)) return;
e.preventDefault();
if (state.phase !== PHASE.PLAYING) return;
pressUp();
};
const getPointerPos = (e) => {
const rect = canvas.getBoundingClientRect();
return { x: e.clientX - rect.left, y: e.clientY - rect.top };
};
const onPointerDown = (e) => {
if (e.pointerType === 'mouse' && e.button !== 0) return;
e.preventDefault();
try { canvas.setPointerCapture(e.pointerId); } catch (err) {}
pressDown(getPointerPos(e));
};
const onPointerUp = (e) => {
if (!state.holding) return;
e.preventDefault();
pressUp();
};
const onPointerCancel = () => {
if (state.holding) { state.holding = false; state.jumpDone = false; }
};
const onResize = () => resize();
window.addEventListener('keydown', onKeyDown);
window.addEventListener('keyup', onKeyUp);
window.addEventListener('resize', onResize);
canvas.addEventListener('pointerdown', onPointerDown);
canvas.addEventListener('pointerup', onPointerUp);
canvas.addEventListener('pointercancel', onPointerCancel);
// ===== Game logic — 100% 跟原本一樣 =====
function releaseShot(holdT) {
const g = geom();
const tNorm = Math.min(1, holdT / CONFIG.JUMP_DURATION);
const offset = tNorm - CONFIG.PERFECT_WINDOW_T;
const absOff = Math.abs(offset);
const jumpY = jumpOffset(tNorm) * (W * CONFIG.JUMP_HEIGHT_RATIO);
const bx = g.ballX;
const by = g.groundY - jumpY;
const tx = g.hoopX;
const ty = g.hoopY;
const T = CONFIG.SHOT_TARGET_TIME;
const vx0 = (tx - bx) / T;
const G = W * CONFIG.GRAVITY_RATIO;
const vy0 = (ty - by - 0.5 * G * T * T) / T - G * CONFIG.EULER_COMPENSATION;
const driftMag = absOff < CONFIG.PERFECT_TOLERANCE
? 0
: Math.min(1, (absOff - CONFIG.PERFECT_TOLERANCE) / (CONFIG.MAX_DRIFT_T - CONFIG.PERFECT_TOLERANCE));
const sign = Math.sign(offset) || (Math.random() < 0.5 ? -1 : 1);
const rand = (Math.random() - 0.5) * 0.4;
const speed = Math.hypot(vx0, vy0);
const angle = Math.atan2(vy0, vx0);
const baseJitter = (Math.random() - 0.5) * 2;
const baseJitter2 = (Math.random() - 0.5) * 2;
const driftMagCurved = driftMag ** 0.4;
const driftSpeed = (sign * driftMag * CONFIG.SHOT_DRIFT_VEL) + rand * 1 * (driftMag ** 3);
const driftAngle = (sign * driftMag * CONFIG.SHOT_DRIFT_ANGLE) + rand * 0.4 * driftMagCurved;
const newSpeed = speed * (1 + baseJitter * CONFIG.PERFECT_JITTER_VEL) * (1 + driftSpeed);
const newAngle = angle + baseJitter2 * CONFIG.PERFECT_JITTER_ANGLE + driftAngle;
const vx = Math.cos(newAngle) * newSpeed;
const vy = Math.sin(newAngle) * newSpeed;
state.balls.push({
id: state.nextBallId++,
x: bx, y: by, vx, vy,
r: g.ballR,
spin: (Math.random() - 0.5) * 8,
rot: 0,
passedRimTopAt: null,
scored: false,
lastBoardHit: 0,
lastRimHit: 0,
bornAt: performance.now(),
});
state.attempts += 1;
state.cooldown = CONFIG.COOLDOWN;
state.ready = false;
SFX.shoot();
}
function jumpOffset(tNorm) {
if (tNorm <= 0 || tNorm >= 1) return 0;
return Math.sin(tNorm * Math.PI);
}
function step(dt) {
if (state.phase !== PHASE.PLAYING) return;
if (state.mode === MODE.TIMED) {
state.timeLeft -= dt;
if (state.timeLeft <= 0) {
state.timeLeft = 0;
state.phase = PHASE.OVER;
SFX.end();
}
}
if (state.holding) {
state.holdT += dt;
if (state.holdT >= CONFIG.JUMP_DURATION) {
state.holdT = CONFIG.JUMP_DURATION;
state.jumpDone = true;
}
}
if (state.cooldown > 0) {
state.cooldown -= dt;
if (state.cooldown <= 0) { state.cooldown = 0; state.ready = true; }
}
const g = geom();
for (const b of state.balls) {
b.prevX = b.x;
b.prevY = b.y;
b.vy += W * CONFIG.GRAVITY_RATIO * dt;
b.vx *= (1 - CONFIG.AIR_DRAG * dt * 60);
b.vy *= (1 - CONFIG.AIR_DRAG * dt * 60);
b.x += b.vx * dt;
b.y += b.vy * dt;
b.rot += b.spin * dt;
collideBackboard(b, g);
collideRim(b, g);
detectScore(b, g);
}
for (let i = 0; i < state.balls.length; i++) {
for (let j = i + 1; j < state.balls.length; j++) {
collideBalls(state.balls[i], state.balls[j]);
}
}
state.balls = state.balls.filter(b => {
const margin = b.r * 4;
return b.x > -margin && b.x < W + margin && b.y < H + margin;
});
state.netImpulse *= Math.exp(-dt * 4);
state.netPhase += dt * 14;
if (state.lastScoreFlash > 0) state.lastScoreFlash -= dt;
}
function collideBackboard(b, g) {
if (b.x + b.r < g.boardX) return;
if (b.x - b.r > g.boardX) return;
if (b.y < g.boardTop - b.r || b.y > g.boardBot + b.r) return;
const cy = Math.max(g.boardTop, Math.min(g.boardBot, b.y));
const dx = b.x - g.boardX;
const dy = b.y - cy;
const d = Math.hypot(dx, dy);
if (d > b.r) return;
if (d === 0) return;
const nx = dx / d, ny = dy / d;
const overlap = b.r - d;
b.x += nx * overlap;
b.y += ny * overlap;
const vn = b.vx * nx + b.vy * ny;
if (vn < 0) {
b.vx -= (1 + CONFIG.RESTITUTION_BOARD) * vn * nx;
b.vy -= (1 + CONFIG.RESTITUTION_BOARD) * vn * ny;
const now = performance.now();
if (now - b.lastBoardHit > 80) { SFX.board(); b.lastBoardHit = now; }
}
}
function collideRim(b, g) {
const front = { x: g.hoopX - g.hoopW / 2, y: g.hoopY };
const back = { x: g.hoopX + g.hoopW / 2, y: g.hoopY };
for (const p of [front, back]) {
const dx = b.x - p.x;
const dy = b.y - p.y;
const d = Math.hypot(dx, dy);
const minD = b.r + g.rimR;
if (d < minD && d > 0) {
const nx = dx / d, ny = dy / d;
const overlap = minD - d;
b.x += nx * overlap;
b.y += ny * overlap;
const vn = b.vx * nx + b.vy * ny;
if (vn < 0) {
b.vx -= (1 + CONFIG.RESTITUTION_RIM) * vn * nx;
b.vy -= (1 + CONFIG.RESTITUTION_RIM) * vn * ny;
const now = performance.now();
if (now - b.lastRimHit > 80) { SFX.rim(); b.lastRimHit = now; }
}
}
}
const armLeft = back.x;
const armRight = g.boardX;
if (b.x > armLeft - b.r && b.x < armRight + b.r) {
const cx = Math.max(armLeft, Math.min(armRight, b.x));
const dx = b.x - cx;
const dy = b.y - g.hoopY;
const d = Math.hypot(dx, dy);
if (d < b.r && d > 0) {
const nx = dx / d, ny = dy / d;
const overlap = b.r - d;
b.x += nx * overlap;
b.y += ny * overlap;
const vn = b.vx * nx + b.vy * ny;
if (vn < 0) {
b.vx -= (1 + CONFIG.RESTITUTION_RIM) * vn * nx;
b.vy -= (1 + CONFIG.RESTITUTION_RIM) * vn * ny;
const now = performance.now();
if (now - b.lastRimHit > 80) { SFX.rim(); b.lastRimHit = now; }
}
}
}
}
function detectScore(b, g) {
if (b.scored) return;
const rimY = g.hoopY;
const xL = g.hoopX - g.hoopW / 2 + g.rimR;
const xR = g.hoopX + g.hoopW / 2 - g.rimR;
if (b.passedRimTopAt === null && b.y < rimY && b.x > xL - b.r && b.x < xR + b.r) {
b.passedRimTopAt = b.y;
}
const prevY = b.prevY != null ? b.prevY : b.y;
if (
!b.scored &&
b.passedRimTopAt !== null &&
b.vy > 0 &&
prevY <= rimY &&
b.y > rimY
) {
if (b.x > xL && b.x < xR) {
b.scored = true;
state.score += 1;
state.lastScoreFlash = 0.5;
state.netImpulse = 1;
const now = performance.now();
const recentlyHit = (now - b.lastRimHit < 250) || (now - b.lastBoardHit < 250);
if (recentlyHit) SFX.score(); else SFX.swish();
}
}
}
function collideBalls(a, b) {
const dx = b.x - a.x;
const dy = b.y - a.y;
const d = Math.hypot(dx, dy);
const minD = a.r + b.r;
if (d >= minD || d === 0) return;
const nx = dx / d, ny = dy / d;
const overlap = minD - d;
a.x -= nx * overlap / 2;
a.y -= ny * overlap / 2;
b.x += nx * overlap / 2;
b.y += ny * overlap / 2;
const rvx = b.vx - a.vx, rvy = b.vy - a.vy;
const vn = rvx * nx + rvy * ny;
if (vn > 0) return;
const e = CONFIG.RESTITUTION_BALL;
const j = -(1 + e) * vn / 2;
a.vx -= j * nx; a.vy -= j * ny;
b.vx += j * nx; b.vy += j * ny;
}
// ===== Rendering =====
function draw() {
const g = geom();
ctx.clearRect(0, 0, W, H);
drawFrame();
drawScore();
drawBottomRight();
drawHoop(g);
drawShooterBall(g);
for (const b of state.balls) drawBall(b);
if (state.phase === PHASE.PLAYING) drawAccuracyBottomLeft();
if (state.phase === PHASE.TITLE) drawTitle();
else if (state.phase === PHASE.OVER) drawGameOver();
}
function drawFrame() {
ctx.save();
ctx.strokeStyle = COLORS.ink;
ctx.lineWidth = 2;
ctx.strokeRect(0.5, 0.5, W - 1, H - 1);
ctx.restore();
}
function drawScore() {
ctx.save();
ctx.fillStyle = COLORS.ink;
const flash = Math.max(0, state.lastScoreFlash);
const scale = 1 + flash * 0.4;
const fontSize = Math.floor(W * 0.085 * scale);
ctx.font = `700 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.textAlign = 'center';
ctx.textBaseline = 'top';
ctx.fillText(String(state.score), W / 2, H * 0.05);
ctx.restore();
}
function drawBottomRight() {
if (state.phase !== PHASE.PLAYING) { exitButton = null; return; }
ctx.save();
if (state.mode === MODE.TIMED) {
ctx.fillStyle = COLORS.ink;
const fontSize = Math.floor(W * 0.05);
ctx.font = `500 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
const t = Math.max(0, state.timeLeft);
const m = Math.floor(t / 60);
const s = Math.floor(t % 60);
const txt = `${m}:${String(s).padStart(2, '0')}`;
ctx.fillText(txt, W - W * 0.05, H - H * 0.04);
exitButton = null;
} else {
// 練習模式:手機沒有 esc 鍵,所以改寫成「回主畫面」
const label = '回主畫面';
const fontSize = Math.floor(W * 0.026);
ctx.font = `500 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
const padX = W * 0.018;
const padY = W * 0.012;
const textW = ctx.measureText(label).width;
const btnW = textW + padX * 2;
const btnH = fontSize + padY * 2;
const btnX = W - W * 0.05 - btnW;
const btnY = H * 0.04;
exitButton = { x: btnX, y: btnY, w: btnW, h: btnH };
ctx.lineWidth = Math.max(1, W * 0.002);
ctx.strokeStyle = COLORS.gray;
ctx.fillStyle = COLORS.paper;
ctx.beginPath();
ctx.rect(btnX, btnY, btnW, btnH);
ctx.fill(); ctx.stroke();
ctx.fillStyle = COLORS.gray;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(label, btnX + btnW / 2, btnY + btnH / 2);
}
ctx.restore();
}
function drawAccuracyBottomLeft() {
ctx.save();
ctx.fillStyle = COLORS.gray;
const fontSize = Math.floor(W * 0.035);
ctx.font = `500 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.textAlign = 'left';
ctx.textBaseline = 'bottom';
const pct = state.attempts > 0 ? Math.round((state.score / state.attempts) * 100) : 0;
const txt = `${state.score}/${state.attempts} (${pct}%)`;
ctx.fillText(txt, W * 0.05, H - H * 0.06);
ctx.restore();
}
function drawHoop(g) {
ctx.save();
ctx.strokeStyle = COLORS.ink;
ctx.lineWidth = Math.max(2, W * 0.005);
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(g.boardX, g.boardTop);
ctx.lineTo(g.boardX, g.boardBot);
ctx.stroke();
ctx.strokeStyle = COLORS.ink;
ctx.lineWidth = Math.max(1, W * 0.003);
ctx.beginPath();
ctx.moveTo(g.hoopX + g.hoopW / 2, g.hoopY);
ctx.lineTo(g.boardX, g.hoopY);
ctx.stroke();
ctx.strokeStyle = COLORS.rim;
ctx.lineWidth = Math.max(2, W * 0.006);
ctx.beginPath();
ctx.moveTo(g.hoopX - g.hoopW / 2, g.hoopY);
ctx.lineTo(g.hoopX + g.hoopW / 2, g.hoopY);
ctx.stroke();
ctx.strokeStyle = COLORS.net;
ctx.lineWidth = Math.max(1, W * 0.0025);
const netLines = 7;
const baseY = g.hoopY;
const bottomY = g.hoopY + g.netDepth;
const leftX = g.hoopX - g.hoopW / 2;
const rightX = g.hoopX + g.hoopW / 2;
const wiggle = state.netImpulse * 4;
for (let i = 0; i <= netLines; i++) {
const t = i / netLines;
const topX = leftX + t * (rightX - leftX);
const bx = leftX + g.hoopW * 0.2 + t * (g.hoopW * 0.6);
const phaseOff = i * 0.7;
const dx = Math.sin(state.netPhase + phaseOff) * wiggle;
ctx.beginPath();
ctx.moveTo(topX, baseY);
ctx.lineTo(bx + dx, bottomY + Math.abs(dx) * 0.3);
ctx.stroke();
}
for (let k = 1; k <= 2; k++) {
const yy = baseY + (g.netDepth * k / 3);
ctx.beginPath();
const dx = Math.sin(state.netPhase + k) * wiggle * 0.6;
ctx.moveTo(leftX + g.hoopW * 0.08 * k, yy);
ctx.lineTo(rightX - g.hoopW * 0.08 * k + dx, yy);
ctx.stroke();
}
ctx.restore();
}
function drawShooterBall(g) {
if (state.phase !== PHASE.PLAYING) return;
if (!state.ready && !state.holding) return;
let yOff = 0;
if (state.holding) {
const tNorm = Math.min(1, state.holdT / CONFIG.JUMP_DURATION);
yOff = jumpOffset(tNorm) * (W * CONFIG.JUMP_HEIGHT_RATIO);
}
drawBallAt(g.ballX, g.groundY - yOff, g.ballR, 0);
}
function drawBall(b) { drawBallAt(b.x, b.y, b.r, b.rot); }
function drawBallAt(x, y, r, rot) {
ctx.save();
if (ballImg) {
ctx.translate(x, y);
ctx.rotate(rot);
ctx.drawImage(ballImg, -r, -r, r * 2, r * 2);
} else {
ctx.fillStyle = COLORS.ball;
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = 'rgba(0,0,0,0.25)';
ctx.lineWidth = Math.max(1, r * 0.08);
ctx.beginPath();
ctx.arc(x, y, r * 0.75, rot, rot + Math.PI);
ctx.stroke();
}
ctx.restore();
}
function drawTitle() {
ctx.save();
ctx.fillStyle = 'rgba(250,250,247,0.85)';
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = COLORS.ink;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `700 ${Math.floor(W * 0.14)}px sans-serif`;
ctx.fillText('🏀🏀🏀', W / 2, H * 0.22);
const btnW = W * 0.7;
const btnH = H * 0.11;
const btnX = (W - btnW) / 2;
const btnGap = H * 0.025;
const btn1Y = H * 0.4;
const btn2Y = btn1Y + btnH + btnGap;
titleButtons = {
timed: { x: btnX, y: btn1Y, w: btnW, h: btnH },
practice: { x: btnX, y: btn2Y, w: btnW, h: btnH },
};
const drawBtn = (b, label, sub) => {
ctx.lineWidth = Math.max(1.5, W * 0.003);
ctx.strokeStyle = COLORS.ink;
ctx.fillStyle = COLORS.paper;
ctx.beginPath();
ctx.rect(b.x, b.y, b.w, b.h);
ctx.fill(); ctx.stroke();
ctx.fillStyle = COLORS.ink;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `600 ${Math.floor(W * 0.04)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText(label, b.x + b.w / 2, b.y + b.h / 2 - W * 0.012);
ctx.font = `400 ${Math.floor(W * 0.026)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText(sub, b.x + b.w / 2, b.y + b.h / 2 + W * 0.022);
};
drawBtn(titleButtons.timed, '1. 限時模式', `${CONFIG.GAME_DURATION} 秒內投進越多越好`);
drawBtn(titleButtons.practice, '2. 練習模式', '不限時,自由輕鬆投');
ctx.font = `400 ${Math.floor(W * 0.027)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillStyle = 'rgba(26,26,26,0.55)';
ctx.fillText('點按鈕選擇模式', W / 2, H * 0.88);
ctx.restore();
}
function drawGameOver() {
ctx.save();
ctx.fillStyle = 'rgba(250,250,247,0.9)';
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = COLORS.ink;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `500 ${Math.floor(W * 0.045)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText('時間到', W / 2, H * 0.36);
ctx.font = `700 ${Math.floor(W * 0.22)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText(String(state.score), W / 2, H * 0.5);
ctx.font = `400 ${Math.floor(W * 0.03)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText('點任何地方再玩一次', W / 2, H * 0.66);
ctx.restore();
}
// ===== Loop =====
let last = performance.now();
let rafId = 0;
function frame(now) {
let dt = (now - last) / 1000;
last = now;
if (dt > 0.05) dt = 0.05;
step(dt);
draw();
rafId = requestAnimationFrame(frame);
}
rafId = requestAnimationFrame(frame);
return () => {
cancelAnimationFrame(rafId);
window.removeEventListener('keydown', onKeyDown);
window.removeEventListener('keyup', onKeyUp);
window.removeEventListener('resize', onResize);
canvas.removeEventListener('pointerdown', onPointerDown);
canvas.removeEventListener('pointerup', onPointerUp);
canvas.removeEventListener('pointercancel', onPointerCancel);
if (actx && actx.state !== 'closed') actx.close().catch(() => {});
};
}
// 啟動!
initGame(document.getElementById('game'), {});
</script>
</body>
</html>

View File

@@ -0,0 +1,881 @@
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>Hoops</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body {
width: 100%; height: 100%;
background: #fafaf7;
overflow: hidden;
overscroll-behavior: none;
user-select: none; -webkit-user-select: none;
touch-action: none;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
#stage {
position: fixed; inset: 0;
display: flex; align-items: center; justify-content: center;
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
#wrap {
position: relative;
/* 取畫面上能擺進的最大正方形 */
width: min(100vw, 100vh);
height: min(100vw, 100vh);
}
canvas {
display: block;
width: 100%; height: 100%;
background: #fafaf7;
touch-action: none;
}
.hint {
position: absolute;
left: 50%; bottom: 8px;
transform: translateX(-50%);
font-size: 5px;
letter-spacing: 0.01em;
opacity: 0.45;
color: #555;
white-space: nowrap;
pointer-events: none;
}
</style>
</head>
<body>
<div id="stage">
<div id="wrap">
<canvas id="game"></canvas>
<div class="hint">by Wiwi Kuan, https://wiwi.blog</div>
</div>
</div>
<script>
// =============================================================================
// CONFIG — 跟原本完全一樣
// =============================================================================
const DEFAULT_CONFIG = {
GAME_DURATION: 60,
COOLDOWN: 0.5,
JUMP_DURATION: 0.5,
JUMP_HEIGHT_RATIO: 0.25,
PERFECT_WINDOW_T: 0.28,
PERFECT_TOLERANCE: 0.001,
MAX_DRIFT_T: 0.35,
GRAVITY_RATIO: 5,
BALL_RADIUS_RATIO: 0.03,
RESTITUTION_RIM: 0.65,
RESTITUTION_BOARD: 0.7,
RESTITUTION_BALL: 0.7,
AIR_DRAG: 0,
SHOT_TARGET_TIME: 0.75,
SHOT_DRIFT_VEL: 0.4,
SHOT_DRIFT_ANGLE: 0.6,
BALL_IMG_SRC: null,
PERFECT_JITTER_VEL: 0.0025,
PERFECT_JITTER_ANGLE: 0.003,
EULER_COMPENSATION: 0.012,
};
const COLORS = {
ink: '#1a1a1a',
paper: '#fafaf7',
ball: '#c2410c',
rim: '#991b1b',
net: '#999',
gray: '#ccc',
};
const PHASE = { TITLE: 'title', PLAYING: 'playing', OVER: 'over' };
const MODE = { TIMED: 'timed', PRACTICE: 'practice' };
// =============================================================================
// 遊戲主體 — 接收 canvas + config,回傳 cleanup function
// 注意:原本是用 parent.clientWidth 取尺寸,這裡改成 wrap 元素的尺寸(其實一樣)
// 並且讓畫布是「正方形 = min(視窗寬, 視窗高)」,跟原本邏輯一致
// =============================================================================
function initGame(canvas, userConfig) {
const CONFIG = Object.assign({}, DEFAULT_CONFIG, userConfig || {});
const ctx = canvas.getContext('2d');
let W = 0, H = 0, DPR = 1;
function resize() {
const parent = canvas.parentElement;
const parentW = parent ? parent.clientWidth : 600;
const parentH = parent ? parent.clientHeight : 600;
// 取較小邊作為正方形邊長
const px = Math.max(280, Math.floor(Math.min(parentW, parentH)));
DPR = Math.max(1, Math.min(2, window.devicePixelRatio || 1));
canvas.style.width = px + 'px';
canvas.style.height = px + 'px';
canvas.width = Math.floor(px * DPR);
canvas.height = Math.floor(px * DPR);
ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
W = px; H = px;
}
resize();
let ballImg = null;
if (CONFIG.BALL_IMG_SRC) {
const img = new Image();
img.onload = () => { ballImg = img; };
img.src = CONFIG.BALL_IMG_SRC;
}
// ===== Audio =====
let actx = null;
function audio() {
if (!actx) {
try { actx = new (window.AudioContext || window.webkitAudioContext)(); }
catch (e) { actx = null; }
}
return actx;
}
function blip({ freq = 440, dur = 0.08, type = 'sine', vol = 0.15, sweep = 0, delay = 0 } = {}) {
const a = audio(); if (!a) return;
const t0 = a.currentTime + delay;
const o = a.createOscillator();
const g = a.createGain();
o.type = type;
o.frequency.setValueAtTime(freq, t0);
if (sweep) o.frequency.exponentialRampToValueAtTime(Math.max(40, freq + sweep), t0 + dur);
g.gain.setValueAtTime(0.0001, t0);
g.gain.exponentialRampToValueAtTime(vol, t0 + 0.005);
g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
o.connect(g).connect(a.destination);
o.start(t0); o.stop(t0 + dur + 0.02);
}
const SFX = {
jump: () => blip({ freq: 220, dur: 0.06, type: 'triangle', vol: 0.08, sweep: 60 }),
shoot: () => blip({ freq: 380, dur: 0.09, type: 'square', vol: 0.07, sweep: 200 }),
rim: () => blip({ freq: 900, dur: 0.05, type: 'square', vol: 0.06, sweep: -300 }),
board: () => blip({ freq: 140, dur: 0.07, type: 'sine', vol: 0.12, sweep: -40 }),
swish: () => {
blip({ freq: 660, dur: 0.08, type: 'sine', vol: 0.10 });
blip({ freq: 990, dur: 0.10, type: 'sine', vol: 0.08, delay: 0.04 });
blip({ freq: 1320, dur: 0.12, type: 'sine', vol: 0.06, delay: 0.09 });
},
score: () => {
blip({ freq: 523, dur: 0.10, type: 'triangle', vol: 0.10 });
blip({ freq: 784, dur: 0.14, type: 'triangle', vol: 0.10, delay: 0.08 });
},
end: () => {
blip({ freq: 220, dur: 0.18, type: 'sawtooth', vol: 0.08 });
blip({ freq: 165, dur: 0.22, type: 'sawtooth', vol: 0.08, delay: 0.12 });
},
};
function geom() {
const hoopX = W * 0.78;
const hoopW = W * 0.085;
const rimR = W * 0.008;
const armLength = W * 0.018;
return {
ballR: W * CONFIG.BALL_RADIUS_RATIO,
ballX: W * 0.18,
groundY: H * 0.72,
hoopX, hoopY: H * 0.42, hoopW, rimR, armLength,
boardX: hoopX + hoopW / 2 + rimR + armLength,
boardTop: H * 0.42 - H * 0.18,
boardBot: H * 0.42 + H * 0.04,
netDepth: H * 0.06,
};
}
const state = {
phase: PHASE.TITLE,
mode: MODE.TIMED,
timeLeft: CONFIG.GAME_DURATION,
score: 0,
attempts: 0,
lastScoreFlash: 0,
holding: false,
holdT: 0,
holdStartTime: 0,
jumpDone: false,
cooldown: 0,
ready: true,
balls: [],
netPhase: 0,
netImpulse: 0,
nextBallId: 1,
};
// 給想作弊的讀者
if (typeof window !== 'undefined') window.__hoops = { state, CONFIG };
let titleButtons = null;
let exitButton = null;
function startGame(mode) {
state.phase = PHASE.PLAYING;
state.mode = mode;
state.timeLeft = CONFIG.GAME_DURATION;
state.score = 0;
state.attempts = 0;
state.lastScoreFlash = 0;
state.holding = false;
state.holdT = 0;
state.holdStartTime = 0;
state.jumpDone = false;
state.cooldown = 0;
state.ready = true;
state.balls = [];
state.netImpulse = 0;
}
function backToTitle() {
state.phase = PHASE.TITLE;
state.holding = false;
state.jumpDone = false;
state.balls = [];
}
function pressDown(pointerPos) {
audio();
if (state.phase === PHASE.OVER) {
backToTitle();
return;
}
if (state.phase === PHASE.TITLE) {
if (pointerPos && titleButtons) {
const { x, y } = pointerPos;
const inBtn = (b) => x >= b.x && x <= b.x + b.w && y >= b.y && y <= b.y + b.h;
if (inBtn(titleButtons.timed)) { startGame(MODE.TIMED); return; }
if (inBtn(titleButtons.practice)) { startGame(MODE.PRACTICE); return; }
}
return;
}
if (state.mode === MODE.PRACTICE && pointerPos && exitButton) {
const { x, y } = pointerPos;
const b = exitButton;
if (x >= b.x && x <= b.x + b.w && y >= b.y && y <= b.y + b.h) {
backToTitle();
return;
}
}
if (!state.ready || state.holding) return;
state.holding = true;
state.holdT = 0;
state.holdStartTime = performance.now();
state.jumpDone = false;
SFX.jump();
}
function pressUp() {
if (!state.holding) return;
state.holding = false;
if (state.jumpDone) return;
const realHoldT = (performance.now() - state.holdStartTime) / 1000;
releaseShot(Math.min(realHoldT, CONFIG.JUMP_DURATION));
}
// ===== Event handlers =====
// App 內不需要擔心捲頁鍵盤事件保留給有實體鍵盤的裝置藍牙鍵盤、Chromebook
const isEditableTarget = (target) => {
if (!target) return false;
const tag = target.tagName || '';
return tag === 'INPUT' || tag === 'TEXTAREA' || target.isContentEditable;
};
const onKeyDown = (e) => {
if (isEditableTarget(e.target)) return;
if (state.phase === PHASE.TITLE) {
if (e.code === 'Digit1' || e.code === 'Numpad1') {
e.preventDefault(); if (e.repeat) return;
audio(); startGame(MODE.TIMED); return;
}
if (e.code === 'Digit2' || e.code === 'Numpad2') {
e.preventDefault(); if (e.repeat) return;
audio(); startGame(MODE.PRACTICE); return;
}
if (e.code === 'Space') e.preventDefault();
return;
}
if (state.phase === PHASE.OVER) {
if (e.code === 'Space') {
e.preventDefault(); if (e.repeat) return;
audio(); backToTitle();
}
return;
}
if (state.mode === MODE.PRACTICE && e.code === 'Escape') {
e.preventDefault(); if (e.repeat) return;
backToTitle(); return;
}
if (e.code !== 'Space') return;
e.preventDefault();
if (e.repeat) return;
pressDown();
};
const onKeyUp = (e) => {
if (e.code !== 'Space') return;
if (isEditableTarget(e.target)) return;
e.preventDefault();
if (state.phase !== PHASE.PLAYING) return;
pressUp();
};
const getPointerPos = (e) => {
const rect = canvas.getBoundingClientRect();
return { x: e.clientX - rect.left, y: e.clientY - rect.top };
};
const onPointerDown = (e) => {
if (e.pointerType === 'mouse' && e.button !== 0) return;
e.preventDefault();
try { canvas.setPointerCapture(e.pointerId); } catch (err) {}
pressDown(getPointerPos(e));
};
const onPointerUp = (e) => {
if (!state.holding) return;
e.preventDefault();
pressUp();
};
const onPointerCancel = () => {
if (state.holding) { state.holding = false; state.jumpDone = false; }
};
const onResize = () => resize();
window.addEventListener('keydown', onKeyDown);
window.addEventListener('keyup', onKeyUp);
window.addEventListener('resize', onResize);
canvas.addEventListener('pointerdown', onPointerDown);
canvas.addEventListener('pointerup', onPointerUp);
canvas.addEventListener('pointercancel', onPointerCancel);
// ===== Game logic — 100% 跟原本一樣 =====
function releaseShot(holdT) {
const g = geom();
const tNorm = Math.min(1, holdT / CONFIG.JUMP_DURATION);
const offset = tNorm - CONFIG.PERFECT_WINDOW_T;
const absOff = Math.abs(offset);
const jumpY = jumpOffset(tNorm) * (W * CONFIG.JUMP_HEIGHT_RATIO);
const bx = g.ballX;
const by = g.groundY - jumpY;
const tx = g.hoopX;
const ty = g.hoopY;
const T = CONFIG.SHOT_TARGET_TIME;
const vx0 = (tx - bx) / T;
const G = W * CONFIG.GRAVITY_RATIO;
const vy0 = (ty - by - 0.5 * G * T * T) / T - G * CONFIG.EULER_COMPENSATION;
const driftMag = absOff < CONFIG.PERFECT_TOLERANCE
? 0
: Math.min(1, (absOff - CONFIG.PERFECT_TOLERANCE) / (CONFIG.MAX_DRIFT_T - CONFIG.PERFECT_TOLERANCE));
const sign = Math.sign(offset) || (Math.random() < 0.5 ? -1 : 1);
const rand = (Math.random() - 0.5) * 0.4;
const speed = Math.hypot(vx0, vy0);
const angle = Math.atan2(vy0, vx0);
const baseJitter = (Math.random() - 0.5) * 2;
const baseJitter2 = (Math.random() - 0.5) * 2;
const driftMagCurved = driftMag ** 0.4;
const driftSpeed = (sign * driftMag * CONFIG.SHOT_DRIFT_VEL) + rand * 1 * (driftMag ** 3);
const driftAngle = (sign * driftMag * CONFIG.SHOT_DRIFT_ANGLE) + rand * 0.4 * driftMagCurved;
const newSpeed = speed * (1 + baseJitter * CONFIG.PERFECT_JITTER_VEL) * (1 + driftSpeed);
const newAngle = angle + baseJitter2 * CONFIG.PERFECT_JITTER_ANGLE + driftAngle;
const vx = Math.cos(newAngle) * newSpeed;
const vy = Math.sin(newAngle) * newSpeed;
state.balls.push({
id: state.nextBallId++,
x: bx, y: by, vx, vy,
r: g.ballR,
spin: (Math.random() - 0.5) * 8,
rot: 0,
passedRimTopAt: null,
scored: false,
lastBoardHit: 0,
lastRimHit: 0,
bornAt: performance.now(),
});
state.attempts += 1;
state.cooldown = CONFIG.COOLDOWN;
state.ready = false;
SFX.shoot();
}
function jumpOffset(tNorm) {
if (tNorm <= 0 || tNorm >= 1) return 0;
return Math.sin(tNorm * Math.PI);
}
function step(dt) {
if (state.phase !== PHASE.PLAYING) return;
if (state.mode === MODE.TIMED) {
state.timeLeft -= dt;
if (state.timeLeft <= 0) {
state.timeLeft = 0;
state.phase = PHASE.OVER;
SFX.end();
}
}
if (state.holding) {
state.holdT += dt;
if (state.holdT >= CONFIG.JUMP_DURATION) {
state.holdT = CONFIG.JUMP_DURATION;
state.jumpDone = true;
}
}
if (state.cooldown > 0) {
state.cooldown -= dt;
if (state.cooldown <= 0) { state.cooldown = 0; state.ready = true; }
}
const g = geom();
for (const b of state.balls) {
b.prevX = b.x;
b.prevY = b.y;
b.vy += W * CONFIG.GRAVITY_RATIO * dt;
b.vx *= (1 - CONFIG.AIR_DRAG * dt * 60);
b.vy *= (1 - CONFIG.AIR_DRAG * dt * 60);
b.x += b.vx * dt;
b.y += b.vy * dt;
b.rot += b.spin * dt;
collideBackboard(b, g);
collideRim(b, g);
detectScore(b, g);
}
for (let i = 0; i < state.balls.length; i++) {
for (let j = i + 1; j < state.balls.length; j++) {
collideBalls(state.balls[i], state.balls[j]);
}
}
state.balls = state.balls.filter(b => {
const margin = b.r * 4;
return b.x > -margin && b.x < W + margin && b.y < H + margin;
});
state.netImpulse *= Math.exp(-dt * 4);
state.netPhase += dt * 14;
if (state.lastScoreFlash > 0) state.lastScoreFlash -= dt;
}
function collideBackboard(b, g) {
if (b.x + b.r < g.boardX) return;
if (b.x - b.r > g.boardX) return;
if (b.y < g.boardTop - b.r || b.y > g.boardBot + b.r) return;
const cy = Math.max(g.boardTop, Math.min(g.boardBot, b.y));
const dx = b.x - g.boardX;
const dy = b.y - cy;
const d = Math.hypot(dx, dy);
if (d > b.r) return;
if (d === 0) return;
const nx = dx / d, ny = dy / d;
const overlap = b.r - d;
b.x += nx * overlap;
b.y += ny * overlap;
const vn = b.vx * nx + b.vy * ny;
if (vn < 0) {
b.vx -= (1 + CONFIG.RESTITUTION_BOARD) * vn * nx;
b.vy -= (1 + CONFIG.RESTITUTION_BOARD) * vn * ny;
const now = performance.now();
if (now - b.lastBoardHit > 80) { SFX.board(); b.lastBoardHit = now; }
}
}
function collideRim(b, g) {
const front = { x: g.hoopX - g.hoopW / 2, y: g.hoopY };
const back = { x: g.hoopX + g.hoopW / 2, y: g.hoopY };
for (const p of [front, back]) {
const dx = b.x - p.x;
const dy = b.y - p.y;
const d = Math.hypot(dx, dy);
const minD = b.r + g.rimR;
if (d < minD && d > 0) {
const nx = dx / d, ny = dy / d;
const overlap = minD - d;
b.x += nx * overlap;
b.y += ny * overlap;
const vn = b.vx * nx + b.vy * ny;
if (vn < 0) {
b.vx -= (1 + CONFIG.RESTITUTION_RIM) * vn * nx;
b.vy -= (1 + CONFIG.RESTITUTION_RIM) * vn * ny;
const now = performance.now();
if (now - b.lastRimHit > 80) { SFX.rim(); b.lastRimHit = now; }
}
}
}
const armLeft = back.x;
const armRight = g.boardX;
if (b.x > armLeft - b.r && b.x < armRight + b.r) {
const cx = Math.max(armLeft, Math.min(armRight, b.x));
const dx = b.x - cx;
const dy = b.y - g.hoopY;
const d = Math.hypot(dx, dy);
if (d < b.r && d > 0) {
const nx = dx / d, ny = dy / d;
const overlap = b.r - d;
b.x += nx * overlap;
b.y += ny * overlap;
const vn = b.vx * nx + b.vy * ny;
if (vn < 0) {
b.vx -= (1 + CONFIG.RESTITUTION_RIM) * vn * nx;
b.vy -= (1 + CONFIG.RESTITUTION_RIM) * vn * ny;
const now = performance.now();
if (now - b.lastRimHit > 80) { SFX.rim(); b.lastRimHit = now; }
}
}
}
}
function detectScore(b, g) {
if (b.scored) return;
const rimY = g.hoopY;
const xL = g.hoopX - g.hoopW / 2 + g.rimR;
const xR = g.hoopX + g.hoopW / 2 - g.rimR;
if (b.passedRimTopAt === null && b.y < rimY && b.x > xL - b.r && b.x < xR + b.r) {
b.passedRimTopAt = b.y;
}
const prevY = b.prevY != null ? b.prevY : b.y;
if (
!b.scored &&
b.passedRimTopAt !== null &&
b.vy > 0 &&
prevY <= rimY &&
b.y > rimY
) {
if (b.x > xL && b.x < xR) {
b.scored = true;
state.score += 1;
state.lastScoreFlash = 0.5;
state.netImpulse = 1;
const now = performance.now();
const recentlyHit = (now - b.lastRimHit < 250) || (now - b.lastBoardHit < 250);
if (recentlyHit) SFX.score(); else SFX.swish();
}
}
}
function collideBalls(a, b) {
const dx = b.x - a.x;
const dy = b.y - a.y;
const d = Math.hypot(dx, dy);
const minD = a.r + b.r;
if (d >= minD || d === 0) return;
const nx = dx / d, ny = dy / d;
const overlap = minD - d;
a.x -= nx * overlap / 2;
a.y -= ny * overlap / 2;
b.x += nx * overlap / 2;
b.y += ny * overlap / 2;
const rvx = b.vx - a.vx, rvy = b.vy - a.vy;
const vn = rvx * nx + rvy * ny;
if (vn > 0) return;
const e = CONFIG.RESTITUTION_BALL;
const j = -(1 + e) * vn / 2;
a.vx -= j * nx; a.vy -= j * ny;
b.vx += j * nx; b.vy += j * ny;
}
// ===== Rendering =====
function draw() {
const g = geom();
ctx.clearRect(0, 0, W, H);
drawFrame();
drawScore();
drawBottomRight();
drawHoop(g);
drawShooterBall(g);
for (const b of state.balls) drawBall(b);
if (state.phase === PHASE.PLAYING) drawAccuracyBottomLeft();
if (state.phase === PHASE.TITLE) drawTitle();
else if (state.phase === PHASE.OVER) drawGameOver();
}
function drawFrame() {
ctx.save();
ctx.strokeStyle = COLORS.ink;
ctx.lineWidth = 2;
ctx.strokeRect(0.5, 0.5, W - 1, H - 1);
ctx.restore();
}
function drawScore() {
ctx.save();
ctx.fillStyle = COLORS.ink;
const flash = Math.max(0, state.lastScoreFlash);
const scale = 1 + flash * 0.4;
const fontSize = Math.floor(W * 0.085 * scale);
ctx.font = `700 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.textAlign = 'center';
ctx.textBaseline = 'top';
ctx.fillText(String(state.score), W / 2, H * 0.05);
ctx.restore();
}
function drawBottomRight() {
if (state.phase !== PHASE.PLAYING) { exitButton = null; return; }
ctx.save();
if (state.mode === MODE.TIMED) {
ctx.fillStyle = COLORS.ink;
const fontSize = Math.floor(W * 0.05);
ctx.font = `500 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
const t = Math.max(0, state.timeLeft);
const m = Math.floor(t / 60);
const s = Math.floor(t % 60);
const txt = `${m}:${String(s).padStart(2, '0')}`;
ctx.fillText(txt, W - W * 0.05, H - H * 0.04);
exitButton = null;
} else {
// 練習模式:手機沒有 esc 鍵,所以改寫成「回主畫面」
const label = '回主畫面';
const fontSize = Math.floor(W * 0.026);
ctx.font = `500 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
const padX = W * 0.018;
const padY = W * 0.012;
const textW = ctx.measureText(label).width;
const btnW = textW + padX * 2;
const btnH = fontSize + padY * 2;
const btnX = W - W * 0.05 - btnW;
const btnY = H * 0.04;
exitButton = { x: btnX, y: btnY, w: btnW, h: btnH };
ctx.lineWidth = Math.max(1, W * 0.002);
ctx.strokeStyle = COLORS.gray;
ctx.fillStyle = COLORS.paper;
ctx.beginPath();
ctx.rect(btnX, btnY, btnW, btnH);
ctx.fill(); ctx.stroke();
ctx.fillStyle = COLORS.gray;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(label, btnX + btnW / 2, btnY + btnH / 2);
}
ctx.restore();
}
function drawAccuracyBottomLeft() {
ctx.save();
ctx.fillStyle = COLORS.gray;
const fontSize = Math.floor(W * 0.035);
ctx.font = `500 ${fontSize}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.textAlign = 'left';
ctx.textBaseline = 'bottom';
const pct = state.attempts > 0 ? Math.round((state.score / state.attempts) * 100) : 0;
const txt = `${state.score}/${state.attempts} (${pct}%)`;
ctx.fillText(txt, W * 0.05, H - H * 0.06);
ctx.restore();
}
function drawHoop(g) {
ctx.save();
ctx.strokeStyle = COLORS.ink;
ctx.lineWidth = Math.max(2, W * 0.005);
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(g.boardX, g.boardTop);
ctx.lineTo(g.boardX, g.boardBot);
ctx.stroke();
ctx.strokeStyle = COLORS.ink;
ctx.lineWidth = Math.max(1, W * 0.003);
ctx.beginPath();
ctx.moveTo(g.hoopX + g.hoopW / 2, g.hoopY);
ctx.lineTo(g.boardX, g.hoopY);
ctx.stroke();
ctx.strokeStyle = COLORS.rim;
ctx.lineWidth = Math.max(2, W * 0.006);
ctx.beginPath();
ctx.moveTo(g.hoopX - g.hoopW / 2, g.hoopY);
ctx.lineTo(g.hoopX + g.hoopW / 2, g.hoopY);
ctx.stroke();
ctx.strokeStyle = COLORS.net;
ctx.lineWidth = Math.max(1, W * 0.0025);
const netLines = 7;
const baseY = g.hoopY;
const bottomY = g.hoopY + g.netDepth;
const leftX = g.hoopX - g.hoopW / 2;
const rightX = g.hoopX + g.hoopW / 2;
const wiggle = state.netImpulse * 4;
for (let i = 0; i <= netLines; i++) {
const t = i / netLines;
const topX = leftX + t * (rightX - leftX);
const bx = leftX + g.hoopW * 0.2 + t * (g.hoopW * 0.6);
const phaseOff = i * 0.7;
const dx = Math.sin(state.netPhase + phaseOff) * wiggle;
ctx.beginPath();
ctx.moveTo(topX, baseY);
ctx.lineTo(bx + dx, bottomY + Math.abs(dx) * 0.3);
ctx.stroke();
}
for (let k = 1; k <= 2; k++) {
const yy = baseY + (g.netDepth * k / 3);
ctx.beginPath();
const dx = Math.sin(state.netPhase + k) * wiggle * 0.6;
ctx.moveTo(leftX + g.hoopW * 0.08 * k, yy);
ctx.lineTo(rightX - g.hoopW * 0.08 * k + dx, yy);
ctx.stroke();
}
ctx.restore();
}
function drawShooterBall(g) {
if (state.phase !== PHASE.PLAYING) return;
if (!state.ready && !state.holding) return;
let yOff = 0;
if (state.holding) {
const tNorm = Math.min(1, state.holdT / CONFIG.JUMP_DURATION);
yOff = jumpOffset(tNorm) * (W * CONFIG.JUMP_HEIGHT_RATIO);
}
drawBallAt(g.ballX, g.groundY - yOff, g.ballR, 0);
}
function drawBall(b) { drawBallAt(b.x, b.y, b.r, b.rot); }
function drawBallAt(x, y, r, rot) {
ctx.save();
if (ballImg) {
ctx.translate(x, y);
ctx.rotate(rot);
ctx.drawImage(ballImg, -r, -r, r * 2, r * 2);
} else {
ctx.fillStyle = COLORS.ball;
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = 'rgba(0,0,0,0.25)';
ctx.lineWidth = Math.max(1, r * 0.08);
ctx.beginPath();
ctx.arc(x, y, r * 0.75, rot, rot + Math.PI);
ctx.stroke();
}
ctx.restore();
}
function drawTitle() {
ctx.save();
ctx.fillStyle = 'rgba(250,250,247,0.85)';
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = COLORS.ink;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `700 ${Math.floor(W * 0.14)}px sans-serif`;
ctx.fillText('🏀🏀🏀', W / 2, H * 0.22);
const btnW = W * 0.7;
const btnH = H * 0.11;
const btnX = (W - btnW) / 2;
const btnGap = H * 0.025;
const btn1Y = H * 0.4;
const btn2Y = btn1Y + btnH + btnGap;
titleButtons = {
timed: { x: btnX, y: btn1Y, w: btnW, h: btnH },
practice: { x: btnX, y: btn2Y, w: btnW, h: btnH },
};
const drawBtn = (b, label, sub) => {
ctx.lineWidth = Math.max(1.5, W * 0.003);
ctx.strokeStyle = COLORS.ink;
ctx.fillStyle = COLORS.paper;
ctx.beginPath();
ctx.rect(b.x, b.y, b.w, b.h);
ctx.fill(); ctx.stroke();
ctx.fillStyle = COLORS.ink;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `600 ${Math.floor(W * 0.04)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText(label, b.x + b.w / 2, b.y + b.h / 2 - W * 0.012);
ctx.font = `400 ${Math.floor(W * 0.026)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText(sub, b.x + b.w / 2, b.y + b.h / 2 + W * 0.022);
};
drawBtn(titleButtons.timed, '1. 限時模式', `${CONFIG.GAME_DURATION} 秒內投進越多越好`);
drawBtn(titleButtons.practice, '2. 練習模式', '不限時,自由輕鬆投');
ctx.font = `400 ${Math.floor(W * 0.027)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillStyle = 'rgba(26,26,26,0.55)';
ctx.fillText('點按鈕選擇模式', W / 2, H * 0.88);
ctx.restore();
}
function drawGameOver() {
ctx.save();
ctx.fillStyle = 'rgba(250,250,247,0.9)';
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = COLORS.ink;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `500 ${Math.floor(W * 0.045)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText('時間到', W / 2, H * 0.36);
ctx.font = `700 ${Math.floor(W * 0.22)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText(String(state.score), W / 2, H * 0.5);
ctx.font = `400 ${Math.floor(W * 0.03)}px ui-monospace, "SF Mono", Menlo, monospace`;
ctx.fillText('點任何地方再玩一次', W / 2, H * 0.66);
ctx.restore();
}
// ===== Loop =====
let last = performance.now();
let rafId = 0;
function frame(now) {
let dt = (now - last) / 1000;
last = now;
if (dt > 0.05) dt = 0.05;
step(dt);
draw();
rafId = requestAnimationFrame(frame);
}
rafId = requestAnimationFrame(frame);
return () => {
cancelAnimationFrame(rafId);
window.removeEventListener('keydown', onKeyDown);
window.removeEventListener('keyup', onKeyUp);
window.removeEventListener('resize', onResize);
canvas.removeEventListener('pointerdown', onPointerDown);
canvas.removeEventListener('pointerup', onPointerUp);
canvas.removeEventListener('pointercancel', onPointerCancel);
if (actx && actx.state !== 'closed') actx.close().catch(() => {});
};
}
// 啟動!
initGame(document.getElementById('game'), {});
</script>
</body>
</html>

View File

@@ -0,0 +1,342 @@
# Baseline profiles for androidx.activity
HSPLandroidx/activity/ComponentActivity$1;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$2;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$3;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$3;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/activity/ComponentActivity$4;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$4;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/activity/ComponentActivity$5;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$5;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/activity/ComponentActivity$6;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$7;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$7;->onContextAvailable(Landroid/content/Context;)V
HSPLandroidx/activity/ComponentActivity;-><init>()V
HSPLandroidx/activity/ComponentActivity;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
HSPLandroidx/activity/ComponentActivity;->ensureViewModelStore()V
HSPLandroidx/activity/ComponentActivity;->getActivityResultRegistry()Landroidx/activity/result/ActivityResultRegistry;
HSPLandroidx/activity/ComponentActivity;->getLifecycle()Landroidx/lifecycle/Lifecycle;
HSPLandroidx/activity/ComponentActivity;->getOnBackPressedDispatcher()Landroidx/activity/OnBackPressedDispatcher;
HSPLandroidx/activity/ComponentActivity;->getSavedStateRegistry()Landroidx/savedstate/SavedStateRegistry;
HSPLandroidx/activity/ComponentActivity;->getViewModelStore()Landroidx/lifecycle/ViewModelStore;
HSPLandroidx/activity/ComponentActivity;->onCreate(Landroid/os/Bundle;)V
HSPLandroidx/activity/OnBackPressedCallback;-><init>(Z)V
HSPLandroidx/activity/OnBackPressedCallback;->addCancellable(Landroidx/activity/Cancellable;)V
HSPLandroidx/activity/OnBackPressedCallback;->remove()V
HSPLandroidx/activity/OnBackPressedCallback;->setEnabled(Z)V
HSPLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;-><init>(Landroidx/activity/OnBackPressedDispatcher;Landroidx/lifecycle/Lifecycle;Landroidx/activity/OnBackPressedCallback;)V
HSPLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;-><init>(Landroidx/activity/OnBackPressedDispatcher;Landroidx/activity/OnBackPressedCallback;)V
HSPLandroidx/activity/OnBackPressedDispatcher;-><init>(Ljava/lang/Runnable;)V
HSPLandroidx/activity/OnBackPressedDispatcher;->addCallback(Landroidx/lifecycle/LifecycleOwner;Landroidx/activity/OnBackPressedCallback;)V
HSPLandroidx/activity/OnBackPressedDispatcher;->addCancellableCallback(Landroidx/activity/OnBackPressedCallback;)Landroidx/activity/Cancellable;
HSPLandroidx/activity/contextaware/ContextAwareHelper;-><init>()V
HSPLandroidx/activity/contextaware/ContextAwareHelper;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
HSPLandroidx/activity/contextaware/ContextAwareHelper;->dispatchOnContextAvailable(Landroid/content/Context;)V
HSPLandroidx/activity/result/ActivityResultLauncher;-><init>()V
HSPLandroidx/activity/result/ActivityResultRegistry$3;-><init>(Landroidx/activity/result/ActivityResultRegistry;Ljava/lang/String;ILandroidx/activity/result/contract/ActivityResultContract;)V
HSPLandroidx/activity/result/ActivityResultRegistry$CallbackAndContract;-><init>(Landroidx/activity/result/ActivityResultCallback;Landroidx/activity/result/contract/ActivityResultContract;)V
HSPLandroidx/activity/result/ActivityResultRegistry;-><init>()V
HSPLandroidx/activity/result/ActivityResultRegistry;->bindRcKey(ILjava/lang/String;)V
HSPLandroidx/activity/result/ActivityResultRegistry;->generateRandomNumber()I
HSPLandroidx/activity/result/ActivityResultRegistry;->register(Ljava/lang/String;Landroidx/activity/result/contract/ActivityResultContract;Landroidx/activity/result/ActivityResultCallback;)Landroidx/activity/result/ActivityResultLauncher;
HSPLandroidx/activity/result/ActivityResultRegistry;->registerKey(Ljava/lang/String;)I
HSPLandroidx/activity/result/contract/ActivityResultContract;-><init>()V
HSPLandroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions;-><init>()V
HSPLandroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;-><init>()V
Landroidx/activity/Cancellable;
Landroidx/activity/ComponentActivity$1;
Landroidx/activity/ComponentActivity$2;
Landroidx/activity/ComponentActivity$3;
Landroidx/activity/ComponentActivity$4;
Landroidx/activity/ComponentActivity$5;
Landroidx/activity/ComponentActivity$6;
Landroidx/activity/ComponentActivity$7;
Landroidx/activity/ComponentActivity$NonConfigurationInstances;
Landroidx/activity/ComponentActivity;
Landroidx/activity/OnBackPressedCallback;
Landroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;
Landroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;
Landroidx/activity/OnBackPressedDispatcher;
Landroidx/activity/OnBackPressedDispatcherOwner;
Landroidx/activity/contextaware/ContextAware;
Landroidx/activity/contextaware/ContextAwareHelper;
Landroidx/activity/contextaware/OnContextAvailableListener;
Landroidx/activity/result/ActivityResult;
Landroidx/activity/result/ActivityResultCallback;
Landroidx/activity/result/ActivityResultCaller;
Landroidx/activity/result/ActivityResultLauncher;
Landroidx/activity/result/ActivityResultRegistry$3;
Landroidx/activity/result/ActivityResultRegistry$CallbackAndContract;
Landroidx/activity/result/ActivityResultRegistry;
Landroidx/activity/result/ActivityResultRegistryOwner;
Landroidx/activity/result/contract/ActivityResultContract;
Landroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions;
Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;
PLandroidx/activity/ComponentActivity$1;->run()V
PLandroidx/activity/ComponentActivity;->access$001(Landroidx/activity/ComponentActivity;)V
PLandroidx/activity/ComponentActivity;->onBackPressed()V
PLandroidx/activity/OnBackPressedCallback;->isEnabled()Z
PLandroidx/activity/OnBackPressedCallback;->removeCancellable(Landroidx/activity/Cancellable;)V
PLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;->cancel()V
PLandroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;->cancel()V
PLandroidx/activity/OnBackPressedDispatcher;->onBackPressed()V
PLandroidx/activity/contextaware/ContextAwareHelper;->clearAvailableContext()V
PLandroidx/activity/result/ActivityResultRegistry$3;->unregister()V
PLandroidx/activity/result/ActivityResultRegistry;->unregister(Ljava/lang/String;)V
Landroidx/activity/Cancellable;
Landroidx/activity/ComponentActivity;
HSPLandroidx/activity/ComponentActivity;-><init>()V
HSPLandroidx/activity/ComponentActivity;-><init>(I)V
HSPLandroidx/activity/ComponentActivity;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
HSPLandroidx/activity/ComponentActivity;->createFullyDrawnExecutor()Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutor;
HSPLandroidx/activity/ComponentActivity;->ensureViewModelStore()V
HSPLandroidx/activity/ComponentActivity;->getActivityResultRegistry()Landroidx/activity/result/ActivityResultRegistry;
HSPLandroidx/activity/ComponentActivity;->getDefaultViewModelCreationExtras()Landroidx/lifecycle/viewmodel/CreationExtras;
HSPLandroidx/activity/ComponentActivity;->getLifecycle()Landroidx/lifecycle/Lifecycle;
HSPLandroidx/activity/ComponentActivity;->getOnBackPressedDispatcher()Landroidx/activity/OnBackPressedDispatcher;
HSPLandroidx/activity/ComponentActivity;->getSavedStateRegistry()Landroidx/savedstate/SavedStateRegistry;
HSPLandroidx/activity/ComponentActivity;->getViewModelStore()Landroidx/lifecycle/ViewModelStore;
HSPLandroidx/activity/ComponentActivity;->lambda$new$2$androidx-activity-ComponentActivity(Landroid/content/Context;)V
HSPLandroidx/activity/ComponentActivity;->onCreate(Landroid/os/Bundle;)V
HSPLandroidx/activity/ComponentActivity;->onTrimMemory(I)V
Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda0;
HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda0;-><init>(Landroidx/activity/ComponentActivity;)V
Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda1;
HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda1;-><init>(Landroidx/activity/ComponentActivity;)V
Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda2;
HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda2;-><init>(Landroidx/activity/ComponentActivity;)V
Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda3;
HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda3;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda3;->onContextAvailable(Landroid/content/Context;)V
Landroidx/activity/ComponentActivity$1;
HSPLandroidx/activity/ComponentActivity$1;-><init>(Landroidx/activity/ComponentActivity;)V
Landroidx/activity/ComponentActivity$2;
HSPLandroidx/activity/ComponentActivity$2;-><init>(Landroidx/activity/ComponentActivity;)V
Landroidx/activity/ComponentActivity$3;
HSPLandroidx/activity/ComponentActivity$3;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$3;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
Landroidx/activity/ComponentActivity$4;
HSPLandroidx/activity/ComponentActivity$4;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$4;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
Landroidx/activity/ComponentActivity$5;
HSPLandroidx/activity/ComponentActivity$5;-><init>(Landroidx/activity/ComponentActivity;)V
HSPLandroidx/activity/ComponentActivity$5;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
Landroidx/activity/ComponentActivity$Api33Impl;
HSPLandroidx/activity/ComponentActivity$Api33Impl;->getOnBackInvokedDispatcher(Landroid/app/Activity;)Landroid/window/OnBackInvokedDispatcher;
Landroidx/activity/ComponentActivity$NonConfigurationInstances;
Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutor;
Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutorApi16Impl;
HSPLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorApi16Impl;-><init>(Landroidx/activity/ComponentActivity;)V
Landroidx/activity/ComponentDialog$$ExternalSyntheticApiModelOutline0;
HSPLandroidx/activity/ComponentDialog$$ExternalSyntheticApiModelOutline0;->m$1(Landroid/view/Window;I)V
HSPLandroidx/activity/ComponentDialog$$ExternalSyntheticApiModelOutline0;->m$1(Landroid/view/Window;Z)V
HSPLandroidx/activity/ComponentDialog$$ExternalSyntheticApiModelOutline0;->m(Landroid/view/Window;I)V
HSPLandroidx/activity/ComponentDialog$$ExternalSyntheticApiModelOutline0;->m(Landroid/view/Window;Z)V
Landroidx/activity/EdgeToEdge;
HSPLandroidx/activity/EdgeToEdge;-><clinit>()V
HSPLandroidx/activity/EdgeToEdge;->enable$default(Landroidx/activity/ComponentActivity;Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;ILjava/lang/Object;)V
HSPLandroidx/activity/EdgeToEdge;->enable(Landroidx/activity/ComponentActivity;Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;)V
Landroidx/activity/EdgeToEdgeApi29;
HSPLandroidx/activity/EdgeToEdgeApi29;-><init>()V
HSPLandroidx/activity/EdgeToEdgeApi29;->setUp(Landroidx/activity/SystemBarStyle;Landroidx/activity/SystemBarStyle;Landroid/view/Window;Landroid/view/View;ZZ)V
Landroidx/activity/EdgeToEdgeImpl;
Landroidx/activity/FullyDrawnReporter;
HSPLandroidx/activity/FullyDrawnReporter;-><init>(Ljava/util/concurrent/Executor;Lkotlin/jvm/functions/Function0;)V
Landroidx/activity/FullyDrawnReporter$$ExternalSyntheticLambda0;
HSPLandroidx/activity/FullyDrawnReporter$$ExternalSyntheticLambda0;-><init>(Landroidx/activity/FullyDrawnReporter;)V
Landroidx/activity/FullyDrawnReporterOwner;
Landroidx/activity/OnBackPressedCallback;
HSPLandroidx/activity/OnBackPressedCallback;-><init>(Z)V
HSPLandroidx/activity/OnBackPressedCallback;->addCancellable(Landroidx/activity/Cancellable;)V
HSPLandroidx/activity/OnBackPressedCallback;->isEnabled()Z
HSPLandroidx/activity/OnBackPressedCallback;->setEnabled(Z)V
HSPLandroidx/activity/OnBackPressedCallback;->setEnabledChangedCallback$activity_release(Lkotlin/jvm/functions/Function0;)V
Landroidx/activity/OnBackPressedDispatcher;
HSPLandroidx/activity/OnBackPressedDispatcher;-><init>(Ljava/lang/Runnable;)V
HSPLandroidx/activity/OnBackPressedDispatcher;->addCallback(Landroidx/lifecycle/LifecycleOwner;Landroidx/activity/OnBackPressedCallback;)V
HSPLandroidx/activity/OnBackPressedDispatcher;->addCancellableCallback$activity_release(Landroidx/activity/OnBackPressedCallback;)Landroidx/activity/Cancellable;
HSPLandroidx/activity/OnBackPressedDispatcher;->hasEnabledCallbacks()Z
HSPLandroidx/activity/OnBackPressedDispatcher;->setOnBackInvokedDispatcher(Landroid/window/OnBackInvokedDispatcher;)V
HSPLandroidx/activity/OnBackPressedDispatcher;->updateBackInvokedCallbackState$activity_release()V
Landroidx/activity/OnBackPressedDispatcher$1;
HSPLandroidx/activity/OnBackPressedDispatcher$1;-><init>(Landroidx/activity/OnBackPressedDispatcher;)V
HSPLandroidx/activity/OnBackPressedDispatcher$1;->invoke()Ljava/lang/Object;
HSPLandroidx/activity/OnBackPressedDispatcher$1;->invoke()V
Landroidx/activity/OnBackPressedDispatcher$2;
HSPLandroidx/activity/OnBackPressedDispatcher$2;-><init>(Landroidx/activity/OnBackPressedDispatcher;)V
Landroidx/activity/OnBackPressedDispatcher$Api33Impl;
HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;-><clinit>()V
HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;-><init>()V
HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;->createOnBackInvokedCallback(Lkotlin/jvm/functions/Function0;)Landroid/window/OnBackInvokedCallback;
Landroidx/activity/OnBackPressedDispatcher$Api33Impl$$ExternalSyntheticLambda0;
HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl$$ExternalSyntheticLambda0;-><init>(Lkotlin/jvm/functions/Function0;)V
Landroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;
HSPLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;-><init>(Landroidx/activity/OnBackPressedDispatcher;Landroidx/lifecycle/Lifecycle;Landroidx/activity/OnBackPressedCallback;)V
HSPLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
Landroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;
HSPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;-><init>(Landroidx/activity/OnBackPressedDispatcher;Landroidx/activity/OnBackPressedCallback;)V
Landroidx/activity/OnBackPressedDispatcherOwner;
Landroidx/activity/R$id;
Landroidx/activity/SystemBarStyle;
HSPLandroidx/activity/SystemBarStyle;-><clinit>()V
HSPLandroidx/activity/SystemBarStyle;-><init>(III)V
HSPLandroidx/activity/SystemBarStyle;-><init>(IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
HSPLandroidx/activity/SystemBarStyle;->getNightMode$activity_release()I
HSPLandroidx/activity/SystemBarStyle;->getScrimWithEnforcedContrast$activity_release(Z)I
HSPLandroidx/activity/SystemBarStyle;->isDark$activity_release(Landroid/content/res/Resources;)Z
Landroidx/activity/SystemBarStyle$Companion;
HSPLandroidx/activity/SystemBarStyle$Companion;-><init>()V
HSPLandroidx/activity/SystemBarStyle$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
HSPLandroidx/activity/SystemBarStyle$Companion;->auto(II)Landroidx/activity/SystemBarStyle;
Landroidx/activity/ViewTreeOnBackPressedDispatcherOwner;
HSPLandroidx/activity/ViewTreeOnBackPressedDispatcherOwner;->set(Landroid/view/View;Landroidx/activity/OnBackPressedDispatcherOwner;)V
Landroidx/activity/contextaware/ContextAware;
Landroidx/activity/contextaware/ContextAwareHelper;
HSPLandroidx/activity/contextaware/ContextAwareHelper;-><init>()V
HSPLandroidx/activity/contextaware/ContextAwareHelper;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
HSPLandroidx/activity/contextaware/ContextAwareHelper;->dispatchOnContextAvailable(Landroid/content/Context;)V
Landroidx/activity/contextaware/OnContextAvailableListener;
Landroidx/activity/result/ActivityResult;
Landroidx/activity/result/ActivityResultCallback;
Landroidx/activity/result/ActivityResultCaller;
Landroidx/activity/result/ActivityResultLauncher;
HSPLandroidx/activity/result/ActivityResultLauncher;-><init>()V
Landroidx/activity/result/ActivityResultRegistry;
HSPLandroidx/activity/result/ActivityResultRegistry;-><init>()V
HSPLandroidx/activity/result/ActivityResultRegistry;->bindRcKey(ILjava/lang/String;)V
HSPLandroidx/activity/result/ActivityResultRegistry;->generateRandomNumber()I
HSPLandroidx/activity/result/ActivityResultRegistry;->register(Ljava/lang/String;Landroidx/activity/result/contract/ActivityResultContract;Landroidx/activity/result/ActivityResultCallback;)Landroidx/activity/result/ActivityResultLauncher;
HSPLandroidx/activity/result/ActivityResultRegistry;->registerKey(Ljava/lang/String;)V
Landroidx/activity/result/ActivityResultRegistry$3;
HSPLandroidx/activity/result/ActivityResultRegistry$3;-><init>(Landroidx/activity/result/ActivityResultRegistry;Ljava/lang/String;Landroidx/activity/result/contract/ActivityResultContract;)V
Landroidx/activity/result/ActivityResultRegistry$CallbackAndContract;
HSPLandroidx/activity/result/ActivityResultRegistry$CallbackAndContract;-><init>(Landroidx/activity/result/ActivityResultCallback;Landroidx/activity/result/contract/ActivityResultContract;)V
Landroidx/activity/result/ActivityResultRegistryOwner;
Landroidx/activity/result/contract/ActivityResultContract;
HSPLandroidx/activity/result/contract/ActivityResultContract;-><init>()V
Landroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions;
HSPLandroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions;-><clinit>()V
HSPLandroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions;-><init>()V
Landroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions$Companion;
HSPLandroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions$Companion;-><init>()V
HSPLandroidx/activity/result/contract/ActivityResultContracts$RequestMultiplePermissions$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;
HSPLandroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;-><clinit>()V
HSPLandroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;-><init>()V
Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult$Companion;
HSPLandroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult$Companion;-><init>()V
HSPLandroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
# Baseline profiles for lifecycle-livedata-core
HSPLandroidx/lifecycle/LiveData$1;-><init>(Landroidx/lifecycle/LiveData;)V
HSPLandroidx/lifecycle/LiveData$1;->run()V
HSPLandroidx/lifecycle/LiveData$AlwaysActiveObserver;-><init>(Landroidx/lifecycle/LiveData;Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/LiveData$AlwaysActiveObserver;->shouldBeActive()Z
HSPLandroidx/lifecycle/LiveData$LifecycleBoundObserver;-><init>(Landroidx/lifecycle/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/LiveData$LifecycleBoundObserver;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/lifecycle/LiveData$LifecycleBoundObserver;->shouldBeActive()Z
HSPLandroidx/lifecycle/LiveData$ObserverWrapper;-><init>(Landroidx/lifecycle/LiveData;Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/LiveData$ObserverWrapper;->activeStateChanged(Z)V
HSPLandroidx/lifecycle/LiveData$ObserverWrapper;->detachObserver()V
HSPLandroidx/lifecycle/LiveData;-><clinit>()V
HSPLandroidx/lifecycle/LiveData;-><init>()V
HSPLandroidx/lifecycle/LiveData;->assertMainThread(Ljava/lang/String;)V
HSPLandroidx/lifecycle/LiveData;->changeActiveCounter(I)V
HSPLandroidx/lifecycle/LiveData;->considerNotify(Landroidx/lifecycle/LiveData$ObserverWrapper;)V
HSPLandroidx/lifecycle/LiveData;->dispatchingValue(Landroidx/lifecycle/LiveData$ObserverWrapper;)V
HSPLandroidx/lifecycle/LiveData;->getValue()Ljava/lang/Object;
HSPLandroidx/lifecycle/LiveData;->getVersion()I
HSPLandroidx/lifecycle/LiveData;->hasActiveObservers()Z
HSPLandroidx/lifecycle/LiveData;->observe(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/LiveData;->observeForever(Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/LiveData;->onActive()V
HSPLandroidx/lifecycle/LiveData;->onInactive()V
HSPLandroidx/lifecycle/LiveData;->postValue(Ljava/lang/Object;)V
HSPLandroidx/lifecycle/LiveData;->removeObserver(Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/LiveData;->setValue(Ljava/lang/Object;)V
HSPLandroidx/lifecycle/MediatorLiveData$Source;-><init>(Landroidx/lifecycle/LiveData;Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/MediatorLiveData$Source;->onChanged(Ljava/lang/Object;)V
HSPLandroidx/lifecycle/MediatorLiveData$Source;->plug()V
HSPLandroidx/lifecycle/MediatorLiveData$Source;->unplug()V
HSPLandroidx/lifecycle/MediatorLiveData;-><init>()V
HSPLandroidx/lifecycle/MediatorLiveData;->addSource(Landroidx/lifecycle/LiveData;Landroidx/lifecycle/Observer;)V
HSPLandroidx/lifecycle/MediatorLiveData;->onActive()V
HSPLandroidx/lifecycle/MediatorLiveData;->onInactive()V
HSPLandroidx/lifecycle/MediatorLiveData;->removeSource(Landroidx/lifecycle/LiveData;)V
HSPLandroidx/lifecycle/MutableLiveData;-><init>()V
HSPLandroidx/lifecycle/MutableLiveData;->setValue(Ljava/lang/Object;)V
PLandroidx/lifecycle/LiveData$LifecycleBoundObserver;->detachObserver()V
# Baseline profiles for Lifecycle ViewModel
HSPLandroidx/lifecycle/ViewModel;-><init>()V
HSPLandroidx/lifecycle/ViewModelLazy;-><init>(Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V
HSPLandroidx/lifecycle/ViewModelLazy;->getValue()Landroidx/lifecycle/ViewModel;
HSPLandroidx/lifecycle/ViewModelLazy;->getValue()Ljava/lang/Object;
HSPLandroidx/lifecycle/ViewModelProvider;-><init>(Landroidx/lifecycle/ViewModelStore;Landroidx/lifecycle/ViewModelProvider$Factory;)V
HSPLandroidx/lifecycle/ViewModelProvider;->get(Ljava/lang/Class;)Landroidx/lifecycle/ViewModel;
HSPLandroidx/lifecycle/ViewModelProvider;->get(Ljava/lang/String;Ljava/lang/Class;)Landroidx/lifecycle/ViewModel;
HSPLandroidx/lifecycle/ViewModelStore;-><init>()V
HSPLandroidx/lifecycle/ViewModelStore;->get(Ljava/lang/String;)Landroidx/lifecycle/ViewModel;
HSPLandroidx/lifecycle/ViewModelStore;->put(Ljava/lang/String;Landroidx/lifecycle/ViewModel;)V
PLandroidx/lifecycle/ViewModel;->clear()V
PLandroidx/lifecycle/ViewModel;->onCleared()V
PLandroidx/lifecycle/ViewModelStore;->clear()V
# Baseline Profile rules for lifecycle-runtime
HPLandroidx/lifecycle/LifecycleRegistry;->backwardPass(Landroidx/lifecycle/LifecycleOwner;)V
HSPLandroidx/lifecycle/LifecycleRegistry$ObserverWithState;-><init>(Landroidx/lifecycle/LifecycleObserver;Landroidx/lifecycle/Lifecycle$State;)V
HSPLandroidx/lifecycle/LifecycleRegistry$ObserverWithState;->dispatchEvent(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/lifecycle/LifecycleRegistry;-><init>(Landroidx/lifecycle/LifecycleOwner;)V
HSPLandroidx/lifecycle/LifecycleRegistry;-><init>(Landroidx/lifecycle/LifecycleOwner;Z)V
HSPLandroidx/lifecycle/LifecycleRegistry;->addObserver(Landroidx/lifecycle/LifecycleObserver;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->calculateTargetState(Landroidx/lifecycle/LifecycleObserver;)Landroidx/lifecycle/Lifecycle$State;
HSPLandroidx/lifecycle/LifecycleRegistry;->enforceMainThreadIfNeeded(Ljava/lang/String;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->forwardPass(Landroidx/lifecycle/LifecycleOwner;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->getCurrentState()Landroidx/lifecycle/Lifecycle$State;
HSPLandroidx/lifecycle/LifecycleRegistry;->handleLifecycleEvent(Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->isSynced()Z
HSPLandroidx/lifecycle/LifecycleRegistry;->min(Landroidx/lifecycle/Lifecycle$State;Landroidx/lifecycle/Lifecycle$State;)Landroidx/lifecycle/Lifecycle$State;
HSPLandroidx/lifecycle/LifecycleRegistry;->moveToState(Landroidx/lifecycle/Lifecycle$State;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->popParentState()V
HSPLandroidx/lifecycle/LifecycleRegistry;->pushParentState(Landroidx/lifecycle/Lifecycle$State;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->removeObserver(Landroidx/lifecycle/LifecycleObserver;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->setCurrentState(Landroidx/lifecycle/Lifecycle$State;)V
HSPLandroidx/lifecycle/LifecycleRegistry;->sync()V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;-><init>()V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPostCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPostResumed(Landroid/app/Activity;)V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPostStarted(Landroid/app/Activity;)V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityResumed(Landroid/app/Activity;)V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityStarted(Landroid/app/Activity;)V
HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->registerIn(Landroid/app/Activity;)V
HSPLandroidx/lifecycle/ReportFragment;-><init>()V
HSPLandroidx/lifecycle/ReportFragment;->dispatch(Landroid/app/Activity;Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/lifecycle/ReportFragment;->dispatch(Landroidx/lifecycle/Lifecycle$Event;)V
HSPLandroidx/lifecycle/ReportFragment;->dispatchCreate(Landroidx/lifecycle/ReportFragment$ActivityInitializationListener;)V
HSPLandroidx/lifecycle/ReportFragment;->dispatchResume(Landroidx/lifecycle/ReportFragment$ActivityInitializationListener;)V
HSPLandroidx/lifecycle/ReportFragment;->dispatchStart(Landroidx/lifecycle/ReportFragment$ActivityInitializationListener;)V
HSPLandroidx/lifecycle/ReportFragment;->injectIfNeededIn(Landroid/app/Activity;)V
HSPLandroidx/lifecycle/ReportFragment;->onActivityCreated(Landroid/os/Bundle;)V
HSPLandroidx/lifecycle/ReportFragment;->onResume()V
HSPLandroidx/lifecycle/ReportFragment;->onStart()V
HSPLandroidx/lifecycle/ViewTreeLifecycleOwner;->set(Landroid/view/View;Landroidx/lifecycle/LifecycleOwner;)V
HSPLandroidx/lifecycle/ViewTreeViewModelStoreOwner;->set(Landroid/view/View;Landroidx/lifecycle/ViewModelStoreOwner;)V
PLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityDestroyed(Landroid/app/Activity;)V
PLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPaused(Landroid/app/Activity;)V
PLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPreDestroyed(Landroid/app/Activity;)V
PLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPrePaused(Landroid/app/Activity;)V
PLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPreStopped(Landroid/app/Activity;)V
PLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityStopped(Landroid/app/Activity;)V
PLandroidx/lifecycle/ReportFragment;->onDestroy()V
PLandroidx/lifecycle/ReportFragment;->onPause()V
PLandroidx/lifecycle/ReportFragment;->onStop()V
# Baseline Profile Rules for androidx.startup
Landroidx/startup/AppInitializer;
HSPLandroidx/startup/AppInitializer;->**(**)**

View File

@@ -0,0 +1,10 @@
{
"version": 3,
"artifactType": {
"type": "COMPATIBLE_SCREEN_MANIFEST",
"kind": "Directory"
},
"applicationId": "blog.wiwi.hoops",
"variantName": "debug",
"elements": []
}

View File

@@ -0,0 +1,10 @@
{
"version": 3,
"artifactType": {
"type": "COMPATIBLE_SCREEN_MANIFEST",
"kind": "Directory"
},
"applicationId": "blog.wiwi.hoops",
"variantName": "release",
"elements": []
}

View File

@@ -0,0 +1 @@
{"options":{"minApiLevel":"24","isDebugModeEnabled":false},"version":"8.13.19"}

View File

@@ -0,0 +1,89 @@
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
# the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
# will be ignored by new version of the Android plugin for Gradle.
# Optimizations: If you don't want to optimize, use the proguard-android.txt configuration file
# instead of this one, which turns off the optimization flags.
-allowaccessmodification
# Preserve some attributes that may be required for reflection.
-keepattributes AnnotationDefault,
EnclosingMethod,
InnerClasses,
RuntimeVisibleAnnotations,
RuntimeVisibleParameterAnnotations,
RuntimeVisibleTypeAnnotations,
Signature
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
-keep public class com.google.android.vending.licensing.ILicensingService
-dontnote com.android.vending.licensing.ILicensingService
-dontnote com.google.vending.licensing.ILicensingService
-dontnote com.google.android.vending.licensing.ILicensingService
# For native methods, see https://www.guardsquare.com/manual/configuration/examples#native
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
# Keep setters in Views so that animations can still work.
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick.
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see https://www.guardsquare.com/manual/configuration/examples#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
}
# Preserve annotated Javascript interface methods.
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
# The support libraries contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontnote android.support.**
-dontnote androidx.**
-dontwarn android.support.**
-dontwarn androidx.**
# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <init>(...);
}
# These classes are duplicated between android.jar and org.apache.http.legacy.jar.
-dontnote org.apache.http.**
-dontnote android.net.http.**
# These classes are duplicated between android.jar and core-lambda-stubs.jar.
-dontnote java.lang.invoke.**

View File

@@ -0,0 +1,95 @@
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
# the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
# will be ignored by new version of the Android plugin for Gradle.
# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize steps (and performs some
# of these optimizations on its own).
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.
-dontoptimize
# Preserve some attributes that may be required for reflection.
-keepattributes AnnotationDefault,
EnclosingMethod,
InnerClasses,
RuntimeVisibleAnnotations,
RuntimeVisibleParameterAnnotations,
RuntimeVisibleTypeAnnotations,
Signature
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
-keep public class com.google.android.vending.licensing.ILicensingService
-dontnote com.android.vending.licensing.ILicensingService
-dontnote com.google.vending.licensing.ILicensingService
-dontnote com.google.android.vending.licensing.ILicensingService
# For native methods, see https://www.guardsquare.com/manual/configuration/examples#native
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
# Keep setters in Views so that animations can still work.
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick.
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see https://www.guardsquare.com/manual/configuration/examples#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
}
# Preserve annotated Javascript interface methods.
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
# The support libraries contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontnote android.support.**
-dontnote androidx.**
-dontwarn android.support.**
-dontwarn androidx.**
# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <init>(...);
}
# These classes are duplicated between android.jar and org.apache.http.legacy.jar.
-dontnote org.apache.http.**
-dontnote android.net.http.**
# These classes are duplicated between android.jar and core-lambda-stubs.jar.
-dontnote java.lang.invoke.**

View File

@@ -0,0 +1,89 @@
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
# the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
# will be ignored by new version of the Android plugin for Gradle.
# Optimizations can be turned on and off in the 'postProcessing' DSL block.
# The configuration below is applied if optimizations are enabled.
-allowaccessmodification
# Preserve some attributes that may be required for reflection.
-keepattributes AnnotationDefault,
EnclosingMethod,
InnerClasses,
RuntimeVisibleAnnotations,
RuntimeVisibleParameterAnnotations,
RuntimeVisibleTypeAnnotations,
Signature
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
-keep public class com.google.android.vending.licensing.ILicensingService
-dontnote com.android.vending.licensing.ILicensingService
-dontnote com.google.vending.licensing.ILicensingService
-dontnote com.google.android.vending.licensing.ILicensingService
# For native methods, see https://www.guardsquare.com/manual/configuration/examples#native
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
# Keep setters in Views so that animations can still work.
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick.
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see https://www.guardsquare.com/manual/configuration/examples#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
}
# Preserve annotated Javascript interface methods.
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
# The support libraries contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontnote android.support.**
-dontnote androidx.**
-dontwarn android.support.**
-dontwarn androidx.**
# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <init>(...);
}
# These classes are duplicated between android.jar and org.apache.http.legacy.jar.
-dontnote org.apache.http.**
-dontnote android.net.http.**
# These classes are duplicated between android.jar and core-lambda-stubs.jar.
-dontnote java.lang.invoke.**

View File

@@ -0,0 +1,5 @@
31=0/.dm
2147483647=0/.dm
28=1/.dm
29=1/.dm
30=1/.dm

View File

@@ -0,0 +1 @@
[{"key":"androidx/startup/AppInitializer.class","name":"androidx/startup/AppInitializer.class","size":7553,"crc":870624420},{"key":"androidx/startup/InitializationProvider.class","name":"androidx/startup/InitializationProvider.class","size":2530,"crc":-159478496},{"key":"androidx/startup/Initializer.class","name":"androidx/startup/Initializer.class","size":555,"crc":-1348991370},{"key":"androidx/startup/StartupException.class","name":"androidx/startup/StartupException.class","size":1051,"crc":-464023827},{"key":"androidx/startup/StartupLogger.class","name":"androidx/startup/StartupLogger.class","size":1324,"crc":1793103804},{"key":"META-INF/androidx.startup_startup-runtime.version","name":"META-INF/androidx.startup_startup-runtime.version","size":6,"crc":1557790284}]

View File

@@ -0,0 +1 @@
[{"key":"META-INF/MANIFEST.MF","name":"META-INF/MANIFEST.MF","size":25,"crc":-301826126},{"key":"META-INF/kotlinx-coroutines-android.kotlin_module","name":"META-INF/kotlinx-coroutines-android.kotlin_module","size":75,"crc":284142387},{"key":"kotlinx/coroutines/android/HandlerContext$scheduleResumeAfterDelay$$inlined$Runnable$1.class","name":"kotlinx/coroutines/android/HandlerContext$scheduleResumeAfterDelay$$inlined$Runnable$1.class","size":2078,"crc":-395684579},{"key":"kotlinx/coroutines/android/HandlerContext$scheduleResumeAfterDelay$1.class","name":"kotlinx/coroutines/android/HandlerContext$scheduleResumeAfterDelay$1.class","size":1831,"crc":804274569},{"key":"kotlinx/coroutines/android/HandlerDispatcherKt.class","name":"kotlinx/coroutines/android/HandlerDispatcherKt.class","size":9480,"crc":245039586},{"key":"kotlinx/coroutines/android/HandlerDispatcherKt$awaitFrame$lambda-3$$inlined$Runnable$1.class","name":"kotlinx/coroutines/android/HandlerDispatcherKt$awaitFrame$lambda-3$$inlined$Runnable$1.class","size":1526,"crc":1247786088},{"key":"kotlinx/coroutines/android/AndroidDispatcherFactory.class","name":"kotlinx/coroutines/android/AndroidDispatcherFactory.class","size":2203,"crc":-1412015008},{"key":"kotlinx/coroutines/android/HandlerDispatcher.class","name":"kotlinx/coroutines/android/HandlerDispatcher.class","size":2358,"crc":-1159760937},{"key":"kotlinx/coroutines/android/AndroidExceptionPreHandler.class","name":"kotlinx/coroutines/android/AndroidExceptionPreHandler.class","size":2871,"crc":-227947537},{"key":"kotlinx/coroutines/android/HandlerContext.class","name":"kotlinx/coroutines/android/HandlerContext.class","size":7940,"crc":800098068},{"key":"META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler","name":"META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler","size":54,"crc":-1889973424},{"key":"META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory","name":"META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory","size":52,"crc":1268078975},{"key":"META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro","name":"META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro","size":899,"crc":2032253094},{"key":"META-INF/com.android.tools/r8-upto-3.0.0/coroutines.pro","name":"META-INF/com.android.tools/r8-upto-3.0.0/coroutines.pro","size":558,"crc":1737114335},{"key":"META-INF/com.android.tools/proguard/coroutines.pro","name":"META-INF/com.android.tools/proguard/coroutines.pro","size":300,"crc":-477435061},{"key":"META-INF/proguard/coroutines.pro","name":"META-INF/proguard/coroutines.pro","size":419,"crc":77044690},{"key":"META-INF/kotlinx_coroutines_android.version","name":"META-INF/kotlinx_coroutines_android.version","size":5,"crc":282843805}]

View File

@@ -0,0 +1 @@
[{"key":"androidx/profileinstaller/BenchmarkOperation$Api21ContextHelper.class","name":"androidx/profileinstaller/BenchmarkOperation$Api21ContextHelper.class","size":784,"crc":910408423},{"key":"androidx/profileinstaller/BenchmarkOperation$Api24ContextHelper.class","name":"androidx/profileinstaller/BenchmarkOperation$Api24ContextHelper.class","size":898,"crc":-1846908175},{"key":"androidx/profileinstaller/BenchmarkOperation.class","name":"androidx/profileinstaller/BenchmarkOperation.class","size":2217,"crc":-235143906},{"key":"androidx/profileinstaller/DeviceProfileWriter.class","name":"androidx/profileinstaller/DeviceProfileWriter.class","size":9901,"crc":1761970309},{"key":"androidx/profileinstaller/DexProfileData.class","name":"androidx/profileinstaller/DexProfileData.class","size":1352,"crc":-447897183},{"key":"androidx/profileinstaller/Encoding.class","name":"androidx/profileinstaller/Encoding.class","size":6317,"crc":-122203374},{"key":"androidx/profileinstaller/FileSectionType.class","name":"androidx/profileinstaller/FileSectionType.class","size":2112,"crc":-2058888424},{"key":"androidx/profileinstaller/ProfileInstallReceiver$ResultDiagnostics.class","name":"androidx/profileinstaller/ProfileInstallReceiver$ResultDiagnostics.class","size":1333,"crc":1824621369},{"key":"androidx/profileinstaller/ProfileInstallReceiver.class","name":"androidx/profileinstaller/ProfileInstallReceiver.class","size":4379,"crc":882371370},{"key":"androidx/profileinstaller/ProfileInstaller$1.class","name":"androidx/profileinstaller/ProfileInstaller$1.class","size":898,"crc":2051655691},{"key":"androidx/profileinstaller/ProfileInstaller$2.class","name":"androidx/profileinstaller/ProfileInstaller$2.class","size":2193,"crc":-26531924},{"key":"androidx/profileinstaller/ProfileInstaller$DiagnosticCode.class","name":"androidx/profileinstaller/ProfileInstaller$DiagnosticCode.class","size":661,"crc":936946104},{"key":"androidx/profileinstaller/ProfileInstaller$DiagnosticsCallback.class","name":"androidx/profileinstaller/ProfileInstaller$DiagnosticsCallback.class","size":445,"crc":-1798863824},{"key":"androidx/profileinstaller/ProfileInstaller$ResultCode.class","name":"androidx/profileinstaller/ProfileInstaller$ResultCode.class","size":653,"crc":1328959836},{"key":"androidx/profileinstaller/ProfileInstaller.class","name":"androidx/profileinstaller/ProfileInstaller.class","size":11365,"crc":-1864137789},{"key":"androidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl.class","name":"androidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl.class","size":1730,"crc":893634560},{"key":"androidx/profileinstaller/ProfileInstallerInitializer$Handler28Impl.class","name":"androidx/profileinstaller/ProfileInstallerInitializer$Handler28Impl.class","size":824,"crc":-353792601},{"key":"androidx/profileinstaller/ProfileInstallerInitializer$Result.class","name":"androidx/profileinstaller/ProfileInstallerInitializer$Result.class","size":471,"crc":-146462361},{"key":"androidx/profileinstaller/ProfileInstallerInitializer.class","name":"androidx/profileinstaller/ProfileInstallerInitializer.class","size":4426,"crc":-941791835},{"key":"androidx/profileinstaller/ProfileTranscoder.class","name":"androidx/profileinstaller/ProfileTranscoder.class","size":21736,"crc":-141864366},{"key":"androidx/profileinstaller/ProfileVerifier$Api33Impl.class","name":"androidx/profileinstaller/ProfileVerifier$Api33Impl.class","size":1385,"crc":-36032257},{"key":"androidx/profileinstaller/ProfileVerifier$Cache.class","name":"androidx/profileinstaller/ProfileVerifier$Cache.class","size":2936,"crc":431451052},{"key":"androidx/profileinstaller/ProfileVerifier$CompilationStatus$ResultCode.class","name":"androidx/profileinstaller/ProfileVerifier$CompilationStatus$ResultCode.class","size":761,"crc":-438192104},{"key":"androidx/profileinstaller/ProfileVerifier$CompilationStatus.class","name":"androidx/profileinstaller/ProfileVerifier$CompilationStatus.class","size":1698,"crc":2010065732},{"key":"androidx/profileinstaller/ProfileVerifier.class","name":"androidx/profileinstaller/ProfileVerifier.class","size":5863,"crc":-1786324660},{"key":"androidx/profileinstaller/ProfileVersion.class","name":"androidx/profileinstaller/ProfileVersion.class","size":1474,"crc":-1261108376},{"key":"androidx/profileinstaller/WritableFileSection.class","name":"androidx/profileinstaller/WritableFileSection.class","size":815,"crc":984045749},{"key":"META-INF/androidx.profileinstaller_profileinstaller.version","name":"META-INF/androidx.profileinstaller_profileinstaller.version","size":6,"crc":-154126649}]

View File

@@ -0,0 +1 @@
[{"key":"androidx/core/splashscreen/MaskedDrawable.class","name":"androidx/core/splashscreen/MaskedDrawable.class","size":2773,"crc":-1354262820},{"key":"androidx/core/splashscreen/SplashScreen$Companion.class","name":"androidx/core/splashscreen/SplashScreen$Companion.class","size":1675,"crc":-2140462775},{"key":"androidx/core/splashscreen/SplashScreen$Impl$setKeepOnScreenCondition$1.class","name":"androidx/core/splashscreen/SplashScreen$Impl$setKeepOnScreenCondition$1.class","size":2545,"crc":-741237898},{"key":"androidx/core/splashscreen/SplashScreen$Impl$setOnExitAnimationListener$2.class","name":"androidx/core/splashscreen/SplashScreen$Impl$setOnExitAnimationListener$2.class","size":2567,"crc":-807334360},{"key":"androidx/core/splashscreen/SplashScreen$Impl.class","name":"androidx/core/splashscreen/SplashScreen$Impl.class","size":10669,"crc":-2114397847},{"key":"androidx/core/splashscreen/SplashScreen$Impl31$hierarchyListener$1.class","name":"androidx/core/splashscreen/SplashScreen$Impl31$hierarchyListener$1.class","size":2140,"crc":-1883408448},{"key":"androidx/core/splashscreen/SplashScreen$Impl31$setKeepOnScreenCondition$1.class","name":"androidx/core/splashscreen/SplashScreen$Impl31$setKeepOnScreenCondition$1.class","size":1815,"crc":71590791},{"key":"androidx/core/splashscreen/SplashScreen$Impl31.class","name":"androidx/core/splashscreen/SplashScreen$Impl31.class","size":8184,"crc":-201717473},{"key":"androidx/core/splashscreen/SplashScreen$KeepOnScreenCondition.class","name":"androidx/core/splashscreen/SplashScreen$KeepOnScreenCondition.class","size":669,"crc":-1257153274},{"key":"androidx/core/splashscreen/SplashScreen$OnExitAnimationListener.class","name":"androidx/core/splashscreen/SplashScreen$OnExitAnimationListener.class","size":922,"crc":-2077345969},{"key":"androidx/core/splashscreen/SplashScreen.class","name":"androidx/core/splashscreen/SplashScreen.class","size":3325,"crc":1433295160},{"key":"androidx/core/splashscreen/SplashScreenViewProvider$ViewImpl$_splashScreenView$2.class","name":"androidx/core/splashscreen/SplashScreenViewProvider$ViewImpl$_splashScreenView$2.class","size":2014,"crc":-66962808},{"key":"androidx/core/splashscreen/SplashScreenViewProvider$ViewImpl.class","name":"androidx/core/splashscreen/SplashScreenViewProvider$ViewImpl.class","size":3428,"crc":-1844359143},{"key":"androidx/core/splashscreen/SplashScreenViewProvider$ViewImpl31.class","name":"androidx/core/splashscreen/SplashScreenViewProvider$ViewImpl31.class","size":3701,"crc":-1166735816},{"key":"androidx/core/splashscreen/SplashScreenViewProvider.class","name":"androidx/core/splashscreen/SplashScreenViewProvider.class","size":2972,"crc":-18991217},{"key":"androidx/core/splashscreen/ThemeUtils$Api31.class","name":"androidx/core/splashscreen/ThemeUtils$Api31.class","size":2566,"crc":490424245},{"key":"androidx/core/splashscreen/ThemeUtils.class","name":"androidx/core/splashscreen/ThemeUtils.class","size":857,"crc":1948239097},{"key":"META-INF/androidx.core_core-splashscreen.version","name":"META-INF/androidx.core_core-splashscreen.version","size":6,"crc":-463103703},{"key":"META-INF/core-splashscreen_release.kotlin_module","name":"META-INF/core-splashscreen_release.kotlin_module","size":24,"crc":-1697843264}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"key":"META-INF/MANIFEST.MF","name":"META-INF/MANIFEST.MF","size":225,"crc":1334212140},{"key":"META-INF/versions/9/module-info.class","name":"META-INF/versions/9/module-info.class","size":287,"crc":-1907208598}]

View File

@@ -0,0 +1 @@
[{"key":"androidx/interpolator/view/animation/FastOutLinearInInterpolator.class","name":"androidx/interpolator/view/animation/FastOutLinearInInterpolator.class","size":2893,"crc":-586218538},{"key":"androidx/interpolator/view/animation/FastOutSlowInInterpolator.class","name":"androidx/interpolator/view/animation/FastOutSlowInInterpolator.class","size":2876,"crc":-1344934723},{"key":"androidx/interpolator/view/animation/LinearOutSlowInInterpolator.class","name":"androidx/interpolator/view/animation/LinearOutSlowInInterpolator.class","size":2882,"crc":-733508970},{"key":"androidx/interpolator/view/animation/LookupTableInterpolator.class","name":"androidx/interpolator/view/animation/LookupTableInterpolator.class","size":907,"crc":-26214147},{"key":"META-INF/androidx.interpolator_interpolator.version","name":"META-INF/androidx.interpolator_interpolator.version","size":6,"crc":-42031000}]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"key":"androidx/savedstate/Recreator$Companion.class","name":"androidx/savedstate/Recreator$Companion.class","size":881,"crc":-2099199957},{"key":"androidx/savedstate/Recreator$SavedStateProvider.class","name":"androidx/savedstate/Recreator$SavedStateProvider.class","size":2367,"crc":1821800407},{"key":"androidx/savedstate/Recreator.class","name":"androidx/savedstate/Recreator.class","size":5559,"crc":-533493763},{"key":"androidx/savedstate/SavedStateRegistry$AutoRecreated.class","name":"androidx/savedstate/SavedStateRegistry$AutoRecreated.class","size":784,"crc":567056175},{"key":"androidx/savedstate/SavedStateRegistry$Companion.class","name":"androidx/savedstate/SavedStateRegistry$Companion.class","size":887,"crc":900872896},{"key":"androidx/savedstate/SavedStateRegistry$SavedStateProvider.class","name":"androidx/savedstate/SavedStateRegistry$SavedStateProvider.class","size":709,"crc":-309935901},{"key":"androidx/savedstate/SavedStateRegistry.class","name":"androidx/savedstate/SavedStateRegistry.class","size":10105,"crc":788600212},{"key":"androidx/savedstate/SavedStateRegistryController$Companion.class","name":"androidx/savedstate/SavedStateRegistryController$Companion.class","size":1607,"crc":-1819286630},{"key":"androidx/savedstate/SavedStateRegistryController.class","name":"androidx/savedstate/SavedStateRegistryController.class","size":4330,"crc":-287729808},{"key":"androidx/savedstate/SavedStateRegistryOwner.class","name":"androidx/savedstate/SavedStateRegistryOwner.class","size":755,"crc":-979039875},{"key":"androidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$1.class","name":"androidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$1.class","size":1846,"crc":423512158},{"key":"androidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$2.class","name":"androidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$2.class","size":2045,"crc":-1356874610},{"key":"androidx/savedstate/ViewTreeSavedStateRegistryOwner.class","name":"androidx/savedstate/ViewTreeSavedStateRegistryOwner.class","size":2543,"crc":1459979664},{"key":"META-INF/androidx.savedstate_savedstate.version","name":"META-INF/androidx.savedstate_savedstate.version","size":6,"crc":1315721634},{"key":"META-INF/savedstate_release.kotlin_module","name":"META-INF/savedstate_release.kotlin_module","size":80,"crc":-912612184}]

View File

@@ -0,0 +1 @@
[{"key":"androidx/versionedparcelable/CustomVersionedParcelable.class","name":"androidx/versionedparcelable/CustomVersionedParcelable.class","size":915,"crc":-363159068},{"key":"androidx/versionedparcelable/NonParcelField.class","name":"androidx/versionedparcelable/NonParcelField.class","size":676,"crc":1361393714},{"key":"androidx/versionedparcelable/ParcelField.class","name":"androidx/versionedparcelable/ParcelField.class","size":762,"crc":-355164638},{"key":"androidx/versionedparcelable/ParcelImpl$1.class","name":"androidx/versionedparcelable/ParcelImpl$1.class","size":1191,"crc":-60532325},{"key":"androidx/versionedparcelable/ParcelImpl.class","name":"androidx/versionedparcelable/ParcelImpl.class","size":1979,"crc":1919067054},{"key":"androidx/versionedparcelable/ParcelUtils.class","name":"androidx/versionedparcelable/ParcelUtils.class","size":5523,"crc":-1129855369},{"key":"androidx/versionedparcelable/VersionedParcel$1.class","name":"androidx/versionedparcelable/VersionedParcel$1.class","size":1546,"crc":-1038307129},{"key":"androidx/versionedparcelable/VersionedParcel$ParcelException.class","name":"androidx/versionedparcelable/VersionedParcel$ParcelException.class","size":538,"crc":1830934000},{"key":"androidx/versionedparcelable/VersionedParcel.class","name":"androidx/versionedparcelable/VersionedParcel.class","size":29325,"crc":142272959},{"key":"androidx/versionedparcelable/VersionedParcelParcel.class","name":"androidx/versionedparcelable/VersionedParcelParcel.class","size":7429,"crc":-328586236},{"key":"androidx/versionedparcelable/VersionedParcelStream$1.class","name":"androidx/versionedparcelable/VersionedParcelStream$1.class","size":1613,"crc":1775874054},{"key":"androidx/versionedparcelable/VersionedParcelStream$FieldBuffer.class","name":"androidx/versionedparcelable/VersionedParcelStream$FieldBuffer.class","size":1288,"crc":1505456534},{"key":"androidx/versionedparcelable/VersionedParcelStream.class","name":"androidx/versionedparcelable/VersionedParcelStream.class","size":13823,"crc":-1859752855},{"key":"androidx/versionedparcelable/VersionedParcelable.class","name":"androidx/versionedparcelable/VersionedParcelable.class","size":148,"crc":752656910},{"key":"androidx/versionedparcelable/VersionedParcelize.class","name":"androidx/versionedparcelable/VersionedParcelize.class","size":964,"crc":886842821},{"key":"META-INF/androidx.versionedparcelable_versionedparcelable.version","name":"META-INF/androidx.versionedparcelable_versionedparcelable.version","size":6,"crc":1557790284}]

View File

@@ -0,0 +1 @@
[{"key":"androidx/lifecycle/Observer.class","name":"androidx/lifecycle/Observer.class","size":581,"crc":-1645925231},{"key":"androidx/lifecycle/LiveData$1.class","name":"androidx/lifecycle/LiveData$1.class","size":967,"crc":1624229709},{"key":"androidx/lifecycle/LiveData$AlwaysActiveObserver.class","name":"androidx/lifecycle/LiveData$AlwaysActiveObserver.class","size":1024,"crc":2056042322},{"key":"androidx/lifecycle/LiveData$LifecycleBoundObserver.class","name":"androidx/lifecycle/LiveData$LifecycleBoundObserver.class","size":2882,"crc":499156433},{"key":"androidx/lifecycle/LiveData$ObserverWrapper.class","name":"androidx/lifecycle/LiveData$ObserverWrapper.class","size":1588,"crc":-1223836256},{"key":"androidx/lifecycle/LiveData.class","name":"androidx/lifecycle/LiveData.class","size":8921,"crc":899075882},{"key":"androidx/lifecycle/MutableLiveData.class","name":"androidx/lifecycle/MutableLiveData.class","size":946,"crc":-710747396},{"key":"META-INF/androidx.lifecycle_lifecycle-livedata-core.version","name":"META-INF/androidx.lifecycle_lifecycle-livedata-core.version","size":78,"crc":1772768774},{"key":"META-INF/lifecycle-livedata-core_release.kotlin_module","name":"META-INF/lifecycle-livedata-core_release.kotlin_module","size":24,"crc":1613429616}]

View File

@@ -0,0 +1 @@
[{"key":"META-INF/MANIFEST.MF","name":"META-INF/MANIFEST.MF","size":25,"crc":-301826126},{"key":"androidx/collection/ArrayMap$1.class","name":"androidx/collection/ArrayMap$1.class","size":2268,"crc":2119754508},{"key":"androidx/collection/ArrayMap.class","name":"androidx/collection/ArrayMap.class","size":3510,"crc":-1266570172},{"key":"androidx/collection/ArraySet$1.class","name":"androidx/collection/ArraySet$1.class","size":2270,"crc":467012598},{"key":"androidx/collection/ArraySet.class","name":"androidx/collection/ArraySet.class","size":11832,"crc":284151195},{"key":"androidx/collection/CircularArray.class","name":"androidx/collection/CircularArray.class","size":4178,"crc":-646150562},{"key":"androidx/collection/CircularIntArray.class","name":"androidx/collection/CircularIntArray.class","size":2996,"crc":-1809371816},{"key":"androidx/collection/ContainerHelpers.class","name":"androidx/collection/ContainerHelpers.class","size":1711,"crc":1459012494},{"key":"androidx/collection/LongSparseArray.class","name":"androidx/collection/LongSparseArray.class","size":7060,"crc":-249107820},{"key":"androidx/collection/LruCache.class","name":"androidx/collection/LruCache.class","size":6572,"crc":-1323386586},{"key":"androidx/collection/MapCollections$ArrayIterator.class","name":"androidx/collection/MapCollections$ArrayIterator.class","size":1678,"crc":-1282301111},{"key":"androidx/collection/MapCollections$EntrySet.class","name":"androidx/collection/MapCollections$EntrySet.class","size":4584,"crc":-1095945835},{"key":"androidx/collection/MapCollections$KeySet.class","name":"androidx/collection/MapCollections$KeySet.class","size":3760,"crc":251514751},{"key":"androidx/collection/MapCollections$MapIterator.class","name":"androidx/collection/MapCollections$MapIterator.class","size":3542,"crc":1838648568},{"key":"androidx/collection/MapCollections$ValuesCollection.class","name":"androidx/collection/MapCollections$ValuesCollection.class","size":3783,"crc":25099165},{"key":"androidx/collection/MapCollections.class","name":"androidx/collection/MapCollections.class","size":5551,"crc":525100092},{"key":"androidx/collection/SimpleArrayMap.class","name":"androidx/collection/SimpleArrayMap.class","size":10631,"crc":41097503},{"key":"androidx/collection/SparseArrayCompat.class","name":"androidx/collection/SparseArrayCompat.class","size":7216,"crc":1400669519}]

View File

@@ -0,0 +1 @@
[{"key":"androidx/annotation/OptIn.class","name":"androidx/annotation/OptIn.class","size":1252,"crc":2044678581},{"key":"androidx/annotation/RequiresOptIn$Level.class","name":"androidx/annotation/RequiresOptIn$Level.class","size":1487,"crc":-1945499205},{"key":"androidx/annotation/RequiresOptIn.class","name":"androidx/annotation/RequiresOptIn.class","size":1119,"crc":1571113326},{"key":"androidx/annotation/experimental/Experimental$Level.class","name":"androidx/annotation/experimental/Experimental$Level.class","size":1570,"crc":-1659833789},{"key":"androidx/annotation/experimental/Experimental.class","name":"androidx/annotation/experimental/Experimental.class","size":1426,"crc":-1756277940},{"key":"androidx/annotation/experimental/UseExperimental.class","name":"androidx/annotation/experimental/UseExperimental.class","size":1521,"crc":-1036664509},{"key":"META-INF/androidx.annotation_annotation-experimental.version","name":"META-INF/androidx.annotation_annotation-experimental.version","size":6,"crc":1914453823},{"key":"META-INF/annotation-experimental_release.kotlin_module","name":"META-INF/annotation-experimental_release.kotlin_module","size":24,"crc":1197092421}]

View File

@@ -0,0 +1 @@
[{"key":"androidx/lifecycle/AbstractSavedStateViewModelFactory$Companion.class","name":"androidx/lifecycle/AbstractSavedStateViewModelFactory$Companion.class","size":981,"crc":-856004234},{"key":"androidx/lifecycle/AbstractSavedStateViewModelFactory.class","name":"androidx/lifecycle/AbstractSavedStateViewModelFactory.class","size":6633,"crc":1887362684},{"key":"androidx/lifecycle/LegacySavedStateHandleController$OnRecreation.class","name":"androidx/lifecycle/LegacySavedStateHandleController$OnRecreation.class","size":3023,"crc":1352335096},{"key":"androidx/lifecycle/LegacySavedStateHandleController$tryToAddRecreator$1.class","name":"androidx/lifecycle/LegacySavedStateHandleController$tryToAddRecreator$1.class","size":2215,"crc":-1110321192},{"key":"androidx/lifecycle/LegacySavedStateHandleController.class","name":"androidx/lifecycle/LegacySavedStateHandleController.class","size":4229,"crc":2063421456},{"key":"androidx/lifecycle/SavedStateHandle$Companion.class","name":"androidx/lifecycle/SavedStateHandle$Companion.class","size":3880,"crc":-1386044437},{"key":"androidx/lifecycle/SavedStateHandle$SavingStateLiveData.class","name":"androidx/lifecycle/SavedStateHandle$SavingStateLiveData.class","size":2785,"crc":1239087543},{"key":"androidx/lifecycle/SavedStateHandle.class","name":"androidx/lifecycle/SavedStateHandle.class","size":13780,"crc":996357302},{"key":"androidx/lifecycle/SavedStateHandleAttacher.class","name":"androidx/lifecycle/SavedStateHandleAttacher.class","size":2410,"crc":-1934335314},{"key":"androidx/lifecycle/SavedStateHandleController.class","name":"androidx/lifecycle/SavedStateHandleController.class","size":3933,"crc":-1321318372},{"key":"androidx/lifecycle/SavedStateHandleSupport$DEFAULT_ARGS_KEY$1.class","name":"androidx/lifecycle/SavedStateHandleSupport$DEFAULT_ARGS_KEY$1.class","size":1015,"crc":424264501},{"key":"androidx/lifecycle/SavedStateHandleSupport$SAVED_STATE_REGISTRY_OWNER_KEY$1.class","name":"androidx/lifecycle/SavedStateHandleSupport$SAVED_STATE_REGISTRY_OWNER_KEY$1.class","size":1095,"crc":1523009794},{"key":"androidx/lifecycle/SavedStateHandleSupport$VIEW_MODEL_STORE_OWNER_KEY$1.class","name":"androidx/lifecycle/SavedStateHandleSupport$VIEW_MODEL_STORE_OWNER_KEY$1.class","size":1077,"crc":-702670968},{"key":"androidx/lifecycle/SavedStateHandleSupport$savedStateHandlesVM$1$1.class","name":"androidx/lifecycle/SavedStateHandleSupport$savedStateHandlesVM$1$1.class","size":1899,"crc":1635032056},{"key":"androidx/lifecycle/SavedStateHandleSupport.class","name":"androidx/lifecycle/SavedStateHandleSupport.class","size":9836,"crc":1960161047},{"key":"androidx/lifecycle/SavedStateHandlesProvider$viewModel$2.class","name":"androidx/lifecycle/SavedStateHandlesProvider$viewModel$2.class","size":1569,"crc":-295120749},{"key":"androidx/lifecycle/SavedStateHandlesProvider.class","name":"androidx/lifecycle/SavedStateHandlesProvider.class","size":5980,"crc":1046935854},{"key":"androidx/lifecycle/SavedStateHandlesVM.class","name":"androidx/lifecycle/SavedStateHandlesVM.class","size":1202,"crc":1705824530},{"key":"androidx/lifecycle/SavedStateViewModelFactory.class","name":"androidx/lifecycle/SavedStateViewModelFactory.class","size":8807,"crc":-1676903485},{"key":"androidx/lifecycle/SavedStateViewModelFactoryKt.class","name":"androidx/lifecycle/SavedStateViewModelFactoryKt.class","size":5061,"crc":2029493689},{"key":"META-INF/androidx.lifecycle_lifecycle-viewmodel-savedstate.version","name":"META-INF/androidx.lifecycle_lifecycle-viewmodel-savedstate.version","size":85,"crc":-1370551005},{"key":"META-INF/lifecycle-viewmodel-savedstate_release.kotlin_module","name":"META-INF/lifecycle-viewmodel-savedstate_release.kotlin_module","size":101,"crc":-1891795020}]

View File

@@ -0,0 +1 @@
[{"key":"META-INF/androidx.tracing_tracing.version","name":"META-INF/androidx.tracing_tracing.version","size":6,"crc":-42031000},{"key":"androidx/tracing/TraceApi18Impl.class","name":"androidx/tracing/TraceApi18Impl.class","size":719,"crc":-735196291},{"key":"androidx/tracing/TraceApi29Impl.class","name":"androidx/tracing/TraceApi29Impl.class","size":975,"crc":-372479716},{"key":"androidx/tracing/Trace.class","name":"androidx/tracing/Trace.class","size":4760,"crc":1193004678}]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"key":"META-INF/MANIFEST.MF","name":"META-INF/MANIFEST.MF","size":25,"crc":-301826126},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$1.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$1.class","size":276,"crc":-940893964},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$AtomicHelper.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$AtomicHelper.class","size":2208,"crc":1918496937},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$Cancellation.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$Cancellation.class","size":1041,"crc":886782754},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$Failure$1.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$Failure$1.class","size":737,"crc":-471209672},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$Failure.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$Failure.class","size":951,"crc":-1760206701},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$Listener.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$Listener.class","size":873,"crc":402316535},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper.class","size":5564,"crc":-1818562924},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$SetFuture.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$SetFuture.class","size":2033,"crc":286080067},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$SynchronizedHelper.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$SynchronizedHelper.class","size":3421,"crc":-1182687467},{"key":"androidx/concurrent/futures/AbstractResolvableFuture$Waiter.class","name":"androidx/concurrent/futures/AbstractResolvableFuture$Waiter.class","size":1723,"crc":226188834},{"key":"androidx/concurrent/futures/AbstractResolvableFuture.class","name":"androidx/concurrent/futures/AbstractResolvableFuture.class","size":18591,"crc":-370636094},{"key":"androidx/concurrent/futures/CallbackToFutureAdapter$Completer.class","name":"androidx/concurrent/futures/CallbackToFutureAdapter$Completer.class","size":3784,"crc":2035088105},{"key":"androidx/concurrent/futures/CallbackToFutureAdapter$FutureGarbageCollectedException.class","name":"androidx/concurrent/futures/CallbackToFutureAdapter$FutureGarbageCollectedException.class","size":706,"crc":-1609752935},{"key":"androidx/concurrent/futures/CallbackToFutureAdapter$Resolver.class","name":"androidx/concurrent/futures/CallbackToFutureAdapter$Resolver.class","size":831,"crc":142665041},{"key":"androidx/concurrent/futures/CallbackToFutureAdapter$SafeFuture$1.class","name":"androidx/concurrent/futures/CallbackToFutureAdapter$SafeFuture$1.class","size":1829,"crc":555402729},{"key":"androidx/concurrent/futures/CallbackToFutureAdapter$SafeFuture.class","name":"androidx/concurrent/futures/CallbackToFutureAdapter$SafeFuture.class","size":3934,"crc":1212043617},{"key":"androidx/concurrent/futures/CallbackToFutureAdapter.class","name":"androidx/concurrent/futures/CallbackToFutureAdapter.class","size":2370,"crc":1014408157},{"key":"androidx/concurrent/futures/DirectExecutor.class","name":"androidx/concurrent/futures/DirectExecutor.class","size":1661,"crc":-2104738324},{"key":"androidx/concurrent/futures/ResolvableFuture.class","name":"androidx/concurrent/futures/ResolvableFuture.class","size":1867,"crc":-254057077}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"key":"androidx/arch/core/executor/ArchTaskExecutor.class","name":"androidx/arch/core/executor/ArchTaskExecutor.class","size":2950,"crc":-173664277},{"key":"androidx/arch/core/executor/DefaultTaskExecutor$1.class","name":"androidx/arch/core/executor/DefaultTaskExecutor$1.class","size":1445,"crc":-1550744660},{"key":"androidx/arch/core/executor/DefaultTaskExecutor$Api28Impl.class","name":"androidx/arch/core/executor/DefaultTaskExecutor$Api28Impl.class","size":834,"crc":1774766260},{"key":"androidx/arch/core/executor/DefaultTaskExecutor.class","name":"androidx/arch/core/executor/DefaultTaskExecutor.class","size":3293,"crc":-1256626107},{"key":"androidx/arch/core/executor/TaskExecutor.class","name":"androidx/arch/core/executor/TaskExecutor.class","size":1053,"crc":1399542030},{"key":"META-INF/androidx.arch.core_core-runtime.version","name":"META-INF/androidx.arch.core_core-runtime.version","size":67,"crc":1307063212}]

View File

@@ -0,0 +1 @@
[{"key":"META-INF/MANIFEST.MF","name":"META-INF/MANIFEST.MF","size":25,"crc":-301826126},{"key":"androidx/arch/core/internal/FastSafeIterableMap.class","name":"androidx/arch/core/internal/FastSafeIterableMap.class","size":2907,"crc":2116950419},{"key":"androidx/arch/core/internal/SafeIterableMap$AscendingIterator.class","name":"androidx/arch/core/internal/SafeIterableMap$AscendingIterator.class","size":1775,"crc":-347866117},{"key":"androidx/arch/core/internal/SafeIterableMap$DescendingIterator.class","name":"androidx/arch/core/internal/SafeIterableMap$DescendingIterator.class","size":1779,"crc":1644932214},{"key":"androidx/arch/core/internal/SafeIterableMap$Entry.class","name":"androidx/arch/core/internal/SafeIterableMap$Entry.class","size":2378,"crc":1824924906},{"key":"androidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions.class","name":"androidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions.class","size":2551,"crc":1452189535},{"key":"androidx/arch/core/internal/SafeIterableMap$ListIterator.class","name":"androidx/arch/core/internal/SafeIterableMap$ListIterator.class","size":2977,"crc":-1002357144},{"key":"androidx/arch/core/internal/SafeIterableMap$SupportRemove.class","name":"androidx/arch/core/internal/SafeIterableMap$SupportRemove.class","size":1208,"crc":1494321347},{"key":"androidx/arch/core/internal/SafeIterableMap.class","name":"androidx/arch/core/internal/SafeIterableMap.class","size":7303,"crc":1636361416},{"key":"androidx/arch/core/util/Function.class","name":"androidx/arch/core/util/Function.class","size":280,"crc":896912248}]

View File

@@ -0,0 +1 @@
[{"key":"META-INF/MANIFEST.MF","name":"META-INF/MANIFEST.MF","size":225,"crc":1808098489},{"key":"META-INF/versions/9/module-info.class","name":"META-INF/versions/9/module-info.class","size":257,"crc":-1911524020}]

View File

@@ -0,0 +1 @@
[{"key":"META-INF/MANIFEST.MF","name":"META-INF/MANIFEST.MF","size":108,"crc":1316044605},{"key":"com/google/common/util/concurrent/ListenableFuture.class","name":"com/google/common/util/concurrent/ListenableFuture.class","size":358,"crc":-1374437012},{"key":"META-INF/maven/com.google.guava/listenablefuture/pom.xml","name":"META-INF/maven/com.google.guava/listenablefuture/pom.xml","size":2226,"crc":65817035},{"key":"META-INF/maven/com.google.guava/listenablefuture/pom.properties","name":"META-INF/maven/com.google.guava/listenablefuture/pom.properties","size":96,"crc":1661854904}]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"key":"androidx/lifecycle/LifecycleRegistry$Companion.class","name":"androidx/lifecycle/LifecycleRegistry$Companion.class","size":2203,"crc":881149842},{"key":"androidx/lifecycle/LifecycleRegistry$ObserverWithState.class","name":"androidx/lifecycle/LifecycleRegistry$ObserverWithState.class","size":3221,"crc":577649636},{"key":"androidx/lifecycle/LifecycleRegistry.class","name":"androidx/lifecycle/LifecycleRegistry.class","size":11316,"crc":1825754494},{"key":"androidx/lifecycle/ReportFragment$ActivityInitializationListener.class","name":"androidx/lifecycle/ReportFragment$ActivityInitializationListener.class","size":672,"crc":137325557},{"key":"androidx/lifecycle/ReportFragment$Companion.class","name":"androidx/lifecycle/ReportFragment$Companion.class","size":3889,"crc":353864254},{"key":"androidx/lifecycle/ReportFragment$LifecycleCallbacks$Companion.class","name":"androidx/lifecycle/ReportFragment$LifecycleCallbacks$Companion.class","size":1657,"crc":-2035159275},{"key":"androidx/lifecycle/ReportFragment$LifecycleCallbacks.class","name":"androidx/lifecycle/ReportFragment$LifecycleCallbacks.class","size":4134,"crc":-1042517223},{"key":"androidx/lifecycle/ReportFragment.class","name":"androidx/lifecycle/ReportFragment.class","size":4770,"crc":-1685581092},{"key":"androidx/lifecycle/ViewTreeLifecycleOwner$findViewTreeLifecycleOwner$1.class","name":"androidx/lifecycle/ViewTreeLifecycleOwner$findViewTreeLifecycleOwner$1.class","size":1786,"crc":1189804573},{"key":"androidx/lifecycle/ViewTreeLifecycleOwner$findViewTreeLifecycleOwner$2.class","name":"androidx/lifecycle/ViewTreeLifecycleOwner$findViewTreeLifecycleOwner$2.class","size":1957,"crc":1482960673},{"key":"androidx/lifecycle/ViewTreeLifecycleOwner.class","name":"androidx/lifecycle/ViewTreeLifecycleOwner.class","size":2382,"crc":-1814616098},{"key":"androidx/lifecycle/LifecycleRegistryOwner.class","name":"androidx/lifecycle/LifecycleRegistryOwner.class","size":628,"crc":-858790333},{"key":"META-INF/androidx.lifecycle_lifecycle-runtime.version","name":"META-INF/androidx.lifecycle_lifecycle-runtime.version","size":72,"crc":1585985631},{"key":"META-INF/lifecycle-runtime_release.kotlin_module","name":"META-INF/lifecycle-runtime_release.kotlin_module","size":70,"crc":1413782649}]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
#Sun May 10 10:16:07 CST 2026
blog.wiwi.hoops.app-main-19\:/drawable/ic_launcher_foreground.xml=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/drawable_ic_launcher_foreground.xml.flat
blog.wiwi.hoops.app-main-19\:/drawable/splash_icon.xml=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/drawable_splash_icon.xml.flat
blog.wiwi.hoops.app-main-19\:/mipmap-anydpi-v26/ic_launcher.xml=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-anydpi-v26_ic_launcher.xml.flat
blog.wiwi.hoops.app-main-19\:/mipmap-anydpi-v26/ic_launcher_round.xml=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-anydpi-v26_ic_launcher_round.xml.flat
blog.wiwi.hoops.app-main-19\:/mipmap-hdpi/ic_launcher.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-hdpi_ic_launcher.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-hdpi/ic_launcher_round.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-hdpi_ic_launcher_round.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-mdpi/ic_launcher.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-mdpi_ic_launcher.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-mdpi/ic_launcher_round.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-mdpi_ic_launcher_round.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-xhdpi/ic_launcher.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-xhdpi_ic_launcher.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-xhdpi/ic_launcher_round.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-xhdpi_ic_launcher_round.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-xxhdpi/ic_launcher.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-xxhdpi_ic_launcher.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-xxhdpi/ic_launcher_round.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-xxhdpi_ic_launcher_round.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-xxxhdpi/ic_launcher.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-xxxhdpi_ic_launcher.png.flat
blog.wiwi.hoops.app-main-19\:/mipmap-xxxhdpi/ic_launcher_round.png=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/mipmap-xxxhdpi_ic_launcher_round.png.flat
blog.wiwi.hoops.app-main-19\:/xml/backup_rules.xml=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/xml_backup_rules.xml.flat
blog.wiwi.hoops.app-main-19\:/xml/data_extraction_rules.xml=/home/wiwi/Documents/Hoops-android/hoops-android/app/build/intermediates/merged_res/debug/mergeDebugResources/xml_data_extraction_rules.xml.flat

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"Antwoord"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"Video"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"Wys af"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"Lui af"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"Inkomende oproep"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"Oproep aan die gang"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"Keur tans \'n inkomende oproep"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"መልስ"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"ቪዲዮ"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"አትቀበል"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"ስልኩን ዝጋ"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"ገቢ ጥሪ"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"እየተካሄደ ያለ ጥሪ"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"ገቢ ጥሪ ማጣራት"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"ردّ"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"فيديو"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"رفض"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"قطع الاتصال"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"مكالمة واردة"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"مكالمة جارية"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"يتم فحص المكالمة الواردة"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"উত্তৰ দিয়ক"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"ভিডিঅ’"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"প্ৰত্যাখ্যান কৰক"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"কল কাটি দিয়ক"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"অন্তৰ্গামী কল"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"চলি থকা কল"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"এটা অন্তৰ্গামী কলৰ পৰীক্ষা কৰি থকা হৈছে"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"৯৯৯+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"Cavab verin"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"Video"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"İmtina edin"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"Dəstəyi asın"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"Gələn zəng"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"Davam edən zəng"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"Gələn zəng göstərilir"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"Odgovori"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"Video"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"Odbij"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"Prekini vezu"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"Dolazni poziv"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"Poziv je u toku"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"Proverava se dolazni poziv"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"Адказаць"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"Відэа"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"Адхіліць"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"Завяршыць"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"Уваходны выклік"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"Бягучы выклік"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"Фільтраванне ўваходнага выкліку"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"Отговор"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"Видеообаждане"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"Отхвърляне"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"Затваряне"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"Входящо обаждане"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"Текущо обаждане"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"Преглежда се входящо обаждане"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"উত্তর দিন"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"ভিডিও"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"বাতিল করুন"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"কল কেটে দিন"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"ইনকামিং কল"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"চালু থাকা কল"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"ইনকামিং কল স্ক্রিনিং করা হচ্ছে"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"৯৯৯+"</string>
</resources>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string msgid="881409763997275156" name="call_notification_answer_action">"Odgovori"</string>
<string msgid="8793775615905189152" name="call_notification_answer_video_action">"Video"</string>
<string msgid="3229508546291798546" name="call_notification_decline_action">"Odbaci"</string>
<string msgid="2659457946726154263" name="call_notification_hang_up_action">"Prekini vezu"</string>
<string msgid="6107532579223922871" name="call_notification_incoming_text">"Dolazni poziv"</string>
<string msgid="8623827134497363134" name="call_notification_ongoing_text">"Poziv u toku"</string>
<string msgid="59049573811482460" name="call_notification_screening_text">"Filtriranje dolaznog poziva"</string>
<string msgid="6277540029070332960" name="status_bar_notification_info_overflow">"999+"</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More