This commit is contained in:
lunaticbum 2026-03-16 15:22:49 +09:00
parent a9fdf9ac9f
commit 1383781dc6
35 changed files with 830 additions and 0 deletions

View File

@ -136,6 +136,7 @@ dependencies {
"include" to listOf("*.aar", "*.jar"),
)))
implementation(project(":gdrive"))
implementation("com.google.android.gms:play-services-wearable:19.0.0")
val kotlinVersion: String? by extra
val realmVersion = "2.0.0"
implementation ("androidx.appcompat:appcompat:1.7.1")

View File

@ -146,6 +146,10 @@
android:enabled="true"
android:exported="false" />
<service
android:name=".workers.WatchGestureService"
android:enabled="true"
android:exported="false" />
<service
android:name=".workers.TorrentService"

View File

@ -0,0 +1,120 @@
(function() {
var retryCount = 0;
var maxRetries = 2;
function tryExtract() {
try {
const newUrl = window.location.origin + window.location.pathname;
const hostname = window.location.hostname;
const contentsType = hostname.includes("book") ? "booktoki" :
hostname.includes("mana") ? "manatoki" :
hostname.includes("new") ? "newtoki" : "web";
// 1. 목차(List) 감지 로직
const listBody = document.querySelector(".list-body");
const novelContent = document.querySelector("#novel_content");
// [중요] 두 핵심 요소가 모두 없으면 재시도 결정
if (!listBody && !novelContent) {
if (retryCount < maxRetries) {
retryCount++;
console.log("DEBUG_LOG: [JS] 요소를 찾지 못해 재시도 중... (" + retryCount + ")");
setTimeout(tryExtract, 500); // 0.5초 후 다시 실행
return;
} else {
console.log("DEBUG_LOG: [JS] 최대 재시도 횟수 초과");
window.webkit.messageHandlers.ContentsRcv.postMessage(JSON.stringify({
'type': 'JP',
'currentUrl' : newUrl
}));
}
return;
}
// --- 1. 목차 추출 실행 ---
if (listBody !== null) {
const contentsArray = [];
const children = listBody.children;
const bookTitleEl = document.querySelector('.view-title span');
const bookTitle = bookTitleEl ? bookTitleEl.innerText.trim() : "Unknown";
const pagination = document.querySelector(".pagination");
let nextPagingUrl = null;
if (pagination) {
const activeLi = pagination.querySelector("li.active");
if (activeLi && activeLi.nextElementSibling) {
const nextA = activeLi.nextElementSibling.querySelector("a");
// 다음 엘리먼트가 존재하고, 'disabled' 클래스가 없으며, href가 있는 경우
if (nextA && nextA.href && !activeLi.nextElementSibling.classList.contains("disabled")) {
nextPagingUrl = nextA.href;
}
}
}
for (let i = 0; i < children.length; i++) {
try {
const wrNumEl = children[i].getElementsByClassName('wr-num')[0];
const wrSubjectA = children[i].getElementsByClassName('wr-subject')[0]?.getElementsByTagName('a')[0];
if (!wrNumEl || !wrSubjectA) continue;
let pageUrl = new URL(wrSubjectA.href, window.location.origin).pathname;
let paths = pageUrl.split('/').filter(p => p);
if (paths.length > 0) {
var lastPart = paths[paths.length - 1];
var isOnlyNumber = lastPart && Array.from(lastPart).every(ch => ch >= '0' && ch <= '9');
if (!isOnlyNumber) paths.pop();
}
pageUrl = "/" + paths.join('/');
contentsArray.push({
'chapterID': parseInt(wrNumEl.textContent.replace(/[^0-9]/g, "")),
'chapterNum': parseInt(wrNumEl.textContent.replace(/[^0-9]/g, "")),
'pathUrl': pageUrl,
'contentsType': contentsType,
'bookPageUrl': window.location.pathname,
'chapterTitle': wrSubjectA.innerText.split('\n').pop().trim(),
'bookTitle': bookTitle,
'currentUrl' : newUrl
});
} catch (e) {}
}
if (contentsArray.length > 0) {
window.webkit.messageHandlers.ContentsRcv.postMessage(JSON.stringify({
'type': 'getListResult',
'contentsType': contentsType,
'bookTitle': bookTitle,
'bookPageUrl': window.location.pathname,
'pages': contentsArray,
'currentUrl' : newUrl,
'nextPagingUrl': nextPagingUrl
}));
return; // 전송 성공 시 종료
}
}
// --- 2. 본문 추출 실행 ---
if (novelContent !== null) {
const titleEl = document.querySelector(".page-desc");
const chapterTitle = titleEl ? titleEl.innerText.trim() : "";
const contents = novelContent.innerText.trim();
if (contents.length > 100) {
window.webkit.messageHandlers.ContentsRcv.postMessage(JSON.stringify({
'type': 'BookContents',
'chapterTitle': chapterTitle,
'bookContents': contents,
'pageUrl' : window.location.pathname,
'currentUrl' : newUrl
}));
}
}
} catch (e) {
console.log("Unified Script Error: " + e);
}
}
// 최초 실행
tryExtract();
})();

View File

@ -0,0 +1,25 @@
package bums.lunatic.launcher.workers
import bums.lunatic.launcher.utils.Blog
import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.WearableListenerService
class WatchGestureService : WearableListenerService() {
override fun onMessageReceived(messageEvent: MessageEvent) {
when (messageEvent.path) {
"/gesture/next" -> {
// 런처의 다음 페이지로 이동하거나, 이북 앱에 키 이벤트 전송
handleGestureAction("NEXT")
}
"/gesture/prev" -> {
handleGestureAction("PREV")
}
}
}
private fun handleGestureAction(action: String) {
// Broadcast를 런처 메인 Activity로 쏘거나,
// 직접 AccessibilityService를 호출하여 시스템 이벤트를 발생시킵니다.
Blog.LOGE("WatchGesture", "Gesture Received: $action")
}
}

View File

@ -17,6 +17,7 @@ plugins {
id ("com.android.library") version "8.10.1" apply false
id ("io.realm.kotlin") version "2.0.0" apply false
id("org.jetbrains.kotlin.android") version kotlinVersion apply false
id("org.jetbrains.kotlin.plugin.compose") version kotlinVersion apply false
}

1
lun_launcher/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,73 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
}
android {
namespace = "bums.lunatic.launcher"
compileSdk = 36
defaultConfig {
applicationId = "bums.lunatic.launcher"
minSdk = 30
targetSdk = 36
versionCode = 1
versionName = "1.0"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
signingConfigs {
getByName("debug") {
storeFile = file("./bs_debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
}
}
}
dependencies {
implementation("com.google.android.gms:play-services-wearable:19.0.0")
implementation(platform("androidx.compose:compose-bom:2024.09.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.wear.compose:compose-material:1.2.1")
implementation("androidx.wear.compose:compose-foundation:1.2.1")
implementation("androidx.wear:wear-tooling-preview:1.0.0")
implementation("androidx.activity:activity-compose:1.12.4")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.wear.tiles:tiles:1.4.0")
implementation("androidx.wear.tiles:tiles-material:1.4.0")
implementation("androidx.wear.tiles:tiles-tooling-preview:1.4.0")
implementation("com.google.android.horologist:horologist-compose-tools:0.6.17")
implementation("com.google.android.horologist:horologist-tiles:0.6.17")
implementation("androidx.wear.watchface:watchface-complications-data-source-ktx:1.2.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2024.09.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
debugImplementation("androidx.wear.tiles:tiles-tooling:1.4.0")
}

8
lun_launcher/lint.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<!-- Ignore the IconLocation for the Tile preview images -->
<issue id="IconLocation">
<ignore path="res/drawable/tile_preview.png" />
<ignore path="res/drawable-round/tile_preview.png" />
</issue>
</lint>

21
lun_launcher/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault">
<service
android:name=".complication.MainComplicationService"
android:exported="true"
android:label="@string/complication_label"
android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
<intent-filter>
<action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
</intent-filter>
<meta-data
android:name="android.support.wearable.complications.SUPPORTED_TYPES"
android:value="SHORT_TEXT" />
<meta-data
android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
android:value="0" />
</service>
<service
android:name=".tile.MainTileService"
android:exported="true"
android:label="@string/tile_label"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>
<meta-data
android:name="androidx.wear.tiles.PREVIEW"
android:resource="@drawable/tile_preview" />
</service>
<uses-library
android:name="com.google.android.wearable"
android:required="true" />
<!--
Set to true if your app is Standalone, that is, it does not require the handheld
app to run.
-->
<meta-data
android:name="com.google.android.wearable.standalone"
android:value="true" />
<activity
android:name=".presentation.MainActivity"
android:exported="true"
android:taskAffinity=""
android:theme="@style/MainActivityTheme.Starting">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,41 @@
package bums.lunatic.launcher.complication
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationType
import androidx.wear.watchface.complications.data.PlainComplicationText
import androidx.wear.watchface.complications.data.ShortTextComplicationData
import androidx.wear.watchface.complications.datasource.ComplicationRequest
import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
import java.util.Calendar
/**
* Skeleton for complication data source that returns short text.
*/
class MainComplicationService : SuspendingComplicationDataSourceService() {
override fun getPreviewData(type: ComplicationType): ComplicationData? {
if (type != ComplicationType.SHORT_TEXT) {
return null
}
return createComplicationData("Mon", "Monday")
}
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData {
return when (Calendar.getInstance().get(Calendar.DAY_OF_WEEK)) {
Calendar.SUNDAY -> createComplicationData("Sun", "Sunday")
Calendar.MONDAY -> createComplicationData("Mon", "Monday")
Calendar.TUESDAY -> createComplicationData("Tue", "Tuesday")
Calendar.WEDNESDAY -> createComplicationData("Wed", "Wednesday")
Calendar.THURSDAY -> createComplicationData("Thu", "Thursday")
Calendar.FRIDAY -> createComplicationData("Fri!", "Friday!")
Calendar.SATURDAY -> createComplicationData("Sat", "Saturday")
else -> throw IllegalArgumentException("too many days")
}
}
private fun createComplicationData(text: String, contentDescription: String) =
ShortTextComplicationData.Builder(
text = PlainComplicationText.Builder(text).build(),
contentDescription = PlainComplicationText.Builder(contentDescription).build()
).build()
}

View File

@ -0,0 +1,104 @@
/* While this template provides a good starting point for using Wear Compose, you can always
* take a look at https://github.com/android/wear-os-samples/tree/main/ComposeStarter to find the
* most up to date changes to the libraries and their usages.
*/
package bums.lunatic.launcher.presentation
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.tooling.preview.devices.WearDevices
import bums.lunatic.launcher.R
import bums.lunatic.launcher.presentation.theme.LunarLauncherTheme
import com.google.android.gms.wearable.MessageClient
import com.google.android.gms.wearable.Wearable
class MainActivity : ComponentActivity() , SensorEventListener {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
setTheme(android.R.style.Theme_DeviceDefault)
setContent {
WearApp("Android")
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
private lateinit var messageClient: MessageClient
private var lastX = 0f
override fun onSensorChanged(p0: SensorEvent?) {
p0?.let { event ->
val x = event.values[0]
// 아주 단순한 Threshold 예시 (나중에 DTW로 교체)
if (x > 15f) { // 오른쪽으로 강하게 휘둘렀을 때
sendGestureToLauncher("/gesture/next")
} else if (x < -15f) {
sendGestureToLauncher("/gesture/prev")
}
lastX = x
}
}
private fun sendGestureToLauncher(path: String) {
// 연결된 노드(폰)를 찾아 메시지 전송
Wearable.getNodeClient(this).connectedNodes.addOnSuccessListener { nodes ->
for (node in nodes) {
Wearable.getMessageClient(this).sendMessage(node.id, path, null)
}
}
}
}
@Composable
fun WearApp(greetingName: String) {
LunarLauncherTheme {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background),
contentAlignment = Alignment.Center
) {
TimeText()
Greeting(greetingName = greetingName)
}
}
}
@Composable
fun Greeting(greetingName: String) {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
color = MaterialTheme.colors.primary,
text = stringResource(R.string.hello_world, greetingName)
)
}
@Preview(device = WearDevices.SMALL_ROUND, showSystemUi = true)
@Composable
fun DefaultPreview() {
WearApp("Preview Android")
}

View File

@ -0,0 +1,17 @@
package bums.lunatic.launcher.presentation.theme
import androidx.compose.runtime.Composable
import androidx.wear.compose.material.MaterialTheme
@Composable
fun LunarLauncherTheme(
content: @Composable () -> Unit
) {
/**
* Empty theme to customize for your app.
* See: https://developer.android.com/jetpack/compose/designsystems/custom
*/
MaterialTheme(
content = content
)
}

View File

@ -0,0 +1,85 @@
package bums.lunatic.launcher.tile
import android.content.Context
import androidx.wear.protolayout.ColorBuilders.argb
import androidx.wear.protolayout.LayoutElementBuilders
import androidx.wear.protolayout.ResourceBuilders
import androidx.wear.protolayout.TimelineBuilders
import androidx.wear.protolayout.material.Colors
import androidx.wear.protolayout.material.Text
import androidx.wear.protolayout.material.Typography
import androidx.wear.protolayout.material.layouts.PrimaryLayout
import androidx.wear.tiles.RequestBuilders
import androidx.wear.tiles.TileBuilders
import androidx.wear.tiles.tooling.preview.Preview
import androidx.wear.tiles.tooling.preview.TilePreviewData
import androidx.wear.tooling.preview.devices.WearDevices
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.tiles.SuspendingTileService
private const val RESOURCES_VERSION = "0"
/**
* Skeleton for a tile with no images.
*/
@OptIn(ExperimentalHorologistApi::class)
class MainTileService : SuspendingTileService() {
override suspend fun resourcesRequest(
requestParams: RequestBuilders.ResourcesRequest
) = resources(requestParams)
override suspend fun tileRequest(
requestParams: RequestBuilders.TileRequest
) = tile(requestParams, this)
}
private fun resources(
requestParams: RequestBuilders.ResourcesRequest
): ResourceBuilders.Resources {
return ResourceBuilders.Resources.Builder()
.setVersion(RESOURCES_VERSION)
.build()
}
private fun tile(
requestParams: RequestBuilders.TileRequest,
context: Context,
): TileBuilders.Tile {
val singleTileTimeline = TimelineBuilders.Timeline.Builder()
.addTimelineEntry(
TimelineBuilders.TimelineEntry.Builder()
.setLayout(
LayoutElementBuilders.Layout.Builder()
.setRoot(tileLayout(requestParams, context))
.build()
)
.build()
)
.build()
return TileBuilders.Tile.Builder()
.setResourcesVersion(RESOURCES_VERSION)
.setTileTimeline(singleTileTimeline)
.build()
}
private fun tileLayout(
requestParams: RequestBuilders.TileRequest,
context: Context,
): LayoutElementBuilders.LayoutElement {
return PrimaryLayout.Builder(requestParams.deviceConfiguration)
.setResponsiveContentInsetEnabled(true)
.setContent(
Text.Builder(context, "Hello World!")
.setColor(argb(Colors.DEFAULT.onSurface))
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.build()
).build()
}
@Preview(device = WearDevices.SMALL_ROUND)
@Preview(device = WearDevices.LARGE_ROUND)
fun tilePreview(context: Context) = TilePreviewData(::resources) {
tile(it, context)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="48dp"
android:height="48dp"
android:gravity="center">
<shape android:shape="oval">
<solid android:color="#FFFFFF" />
</shape>
</item>
<item
android:width="40dp"
android:height="40dp"
android:gravity="center">
<vector
android:width="24dp"
android:height="24dp"
android:tint="#000000"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M17.6,11.48 L19.44,8.3a0.63,0.63 0,0 0,-1.09 -0.63l-1.88,3.24a11.43,11.43 0,0 0,-8.94 0L5.65,7.67a0.63,0.63 0,0 0,-1.09 0.63L6.4,11.48A10.81,10.81 0,0 0,1 20L23,20A10.81,10.81 0,0 0,17.6 11.48ZM7,17.25A1.25,1.25 0,1 1,8.25 16,1.25 1.25,0 0,1 7,17.25ZM17,17.25A1.25,1.25 0,1 1,18.25 16,1.25 1.25,0 0,1 17,17.25Z" />
</vector>
</item>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,3 @@
<resources>
<string name="hello_world">From the Round world,\nHello, %1$s!</string>
</resources>

View File

@ -0,0 +1,10 @@
<resources>
<string name="app_name">lunLauncher</string>
<!--
This string is used for square devices and overridden by hello_world in
values-round/strings.xml for round devices.
-->
<string name="hello_world">From the Square world,\nHello, %1$s!</string>
<string name="tile_label">Example tile</string>
<string name="complication_label">Example complication</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<style name="MainActivityTheme.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@android:color/black</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
<item name="postSplashScreenTheme">@android:style/Theme.DeviceDefault</item>
</style>
</resources>

View File

@ -24,3 +24,4 @@ dependencyResolutionManagement {
rootProject.name = "LunarLauncher"
include ("app","library","utils")
include(":gdrive")
include(":lun_launcher")