SpringBoard-like v1

This commit is contained in:
Annie 2025-04-04 00:50:40 +03:00
parent 70088d37e0
commit 29fade983d
14 changed files with 257 additions and 32 deletions

1
.gitignore vendored
View file

@ -90,7 +90,6 @@ out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/

View file

@ -1,2 +1,13 @@
This is the Vue 3 + Vite template branch.
If you want to download this for use, this is not a working Bridge Launcher Project, but a template. In that case select a different branch.
# SpringBoard-like
A Brige Launcher Project inspired by SpringBoard, iOS default launcher,
# Screenshots
*none because still in development*
# Customizing dock apps
1. Open [Dock.vue](src/components/Dock.vue)
2. On your phone (or dev env), select the *invisible* text below the icon's label name. Copy it fully.
> Note: Thats the **Package name** of the app you want to pin on the dock
3. Put the wanted app's package name instead of the default one

1
dist/assets/index-Byzfhg1j.css vendored Normal file
View file

@ -0,0 +1 @@
body{margin:0;padding:0;box-sizing:border-box;background-color:gray}#applist{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scroll-snap-stop:always}#applist-wrapper{width:100%}.applist-page{scroll-snap-align:start;display:flex;flex-direction:row;flex-wrap:wrap;min-width:100vw;justify-content:flex-start;align-content:flex-start;padding-bottom:10%;padding-top:5%}.applist-page>*{min-width:25%;margin-bottom:5%}#dock{padding:5%;margin:5%;gap:15px;border-radius:24px;background-color:#00000040;border:1px solid white;display:flex;justify-content:center;position:fixed;bottom:0;left:0;right:0}.section{padding:5%;margin:0 5% 5%;border-radius:15px;background-color:#00000040;border:1px solid white;width:100%}.ui-button{border:none;border:1px solid white;border-radius:6px;padding:2%;background-color:#00000080;color:#fff;margin:1%}.app-icon[data-v-fa001907]{display:flex;align-items:center;flex-direction:column;width:max-content;height:max-content}.app-icon .app-icon[data-v-fa001907]>*:nth-child(n+2){padding-bottom:10px}.app-image[data-v-fa001907]{width:60px;height:60px;border-radius:12px}.app-label[data-v-fa001907]{font-size:12px;color:var(--label-color)}.app-package[data-v-fa001907]{font-size:3px;color:#0000}

17
dist/assets/index-C4iP7xdQ.js vendored Normal file

File diff suppressed because one or more lines are too long

14
dist/index.html vendored Normal file
View file

@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SpringBoard</title>
<script type="module" crossorigin src="/assets/index-C4iP7xdQ.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Byzfhg1j.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

1
dist/vite.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

1
dist/vue.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
<title>SpringBoard</title>
</head>
<body>
<div id="app"></div>

View file

@ -1,29 +1,41 @@
<template>
This is a <strong>TEMPLATE</strong>
<Suspense>
<template #default>
<div>
<AppIcon v-for="app in apps" :key="app.packageName" :packageName="app.packageName" :label="app.label" />
</div>
</template>
</Suspense>
<div id="applist-wrapper">
<Suspense>
<template #default>
<div id="applist">
<div class="applist-page" v-for="(page, index) in paginatedApps" :key="index">
<AppIcon v-for="app in page" :key="app.packageName" :packageName="app.packageName" :label="app.label" />
</div>
<div class="applist-page" v-if="paginatedApps.length > 0">
<Settings></Settings>
</div>
</div>
</template>
</Suspense>
</div>
<Dock></Dock>
</template>
<script setup>
import { ref } from 'vue'
import AppIcon from './components/AppIcon.vue'
import { ref, computed } from 'vue';
import AppIcon from './components/AppIcon.vue';
import Dock from './components/Dock.vue';
import Settings from './components/Settings.vue';
const apps = ref([])
async function loadApps() {
const resp = await fetch(Bridge.getAppsURL())
const data = await resp.json()
apps.value = data.apps
apps.value = data.apps.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }))
}
loadApps()
const itemsPerPage = 4 * 6;
const paginatedApps = computed(() => {
return Array(Math.ceil(apps.value.length / itemsPerPage)).fill().map((_, index) => {
return apps.value.slice(index * itemsPerPage, (index + 1) * itemsPerPage);
});
})
</script>
<style>
</style>

View file

@ -5,23 +5,49 @@ import { defineProps, ref, onMounted } from 'vue'
const props = defineProps({
packageName: {
type: String,
required: true
required: true,
},
label: {
type: String,
required: true
required: false,
default: "UNSETLABEL"
},
hideLabel: {
type: Boolean,
required: false,
}
})
let darkLabel
if (Bridge.getSystemNightMode() == 'yes') {
darkLabel = true;
} else {
darkLabel = false;
}
// Create a ref to hold the icon URL
const icon = ref('');
icon.value = await Bridge.getDefaultAppIconURL(props.packageName);
const label = ref('')
if (props.label.length >= 10) {
label.value = `${props.label.slice(0, 10 - 3).trim()}...`;
} else {
label.value = props.label;
}
function handleClick() {
Bridge.requestLaunchApp(props.packageName);
}
</script>
<template>
<div class="app-icon">
<img :src="icon" :alt="props.label" />
<span>{{ props.label }}</span>
<div
class="app-icon"
@click="handleClick()"
:style="{ '--label-color': darkLabel ? '#000000' : '#ffffff' }"
>
<img :src="icon" :alt="label" class="app-image">
<span v-if="!props.hideLabel" class="app-label">{{ label }}</span>
<span v-if="!props.hideLabel" class="app-package">{{ props.packageName }}</span>
</div>
</template>
@ -29,15 +55,28 @@ icon.value = await Bridge.getDefaultAppIconURL(props.packageName);
.app-icon {
display: flex;
align-items: center;
flex-direction: column;
width: max-content;
height: max-content;
.app-icon > *:nth-child(n+2) {
padding-bottom: 10px;
}
}
.app-icon img {
width: 50px;
height: 50px;
.app-image {
width: 60px;
height: 60px;
border-radius: 12px;
}
.app-icon span {
font-size: 14px;
color: #333;
.app-label {
font-size: 12px;
color: var(--label-color);
}
.app-package {
font-size: 3px;
color: #00000000;
}
</style>

14
src/components/Dock.vue Normal file
View file

@ -0,0 +1,14 @@
<script setup>
import AppIcon from './AppIcon.vue'
</script>
<template>
<Suspense>
<div id="dock">
<AppIcon packageName="app.revenge" :hideLabel="true"/>
<AppIcon packageName="com.radolyn.ayugram" :hideLabel="true"/>
<AppIcon packageName="org.mozilla.fennec_fdroid" :hideLabel="true"/>
<AppIcon packageName="org.akanework.gramophone" :hideLabel="true"/>
</div>
</Suspense>
</template>

View file

@ -0,0 +1,53 @@
<script setup>
function toggleBridgeButton() {
console.log('Changed Bridge Button visibility to...')
if (Bridge.getBridgeButtonVisibility() == 'shown') {
Bridge.requestSetBridgeButtonVisibility('hidden');
console.log('hidden');
} else {
Bridge.requestSetBridgeButtonVisibility('shown');
console.log('shown');
}
}
function toggleSystemWallpapers() {
console.log('Changed system wallpapers to...')
if (Bridge.getDrawSystemWallpaperBehindWebViewEnabled()) {
Bridge.requestSetDrawSystemWallpaperBehindWebViewEnabled(false);
console.log('false');
} else {
Bridge.requestSetDrawSystemWallpaperBehindWebViewEnabled(true);
console.log('true');
}
}
function toggleOverscrolling() {
console.log('Changed overscrolling effect to...')
if (Bridge.getOverscrollEffects == 'default') {
Bridge.requestSetOverscrollEffects('none');
console.log('none');
} else {
Bridge.requestSetOverscrollEffects('default');
console.log('default');
}
}
function openBridgeAppDrawer() {
Bridge.requestOpenBridgeAppDrawer();
}
function reloadWindow() {
window.location.reload();
}
</script>
<template>
<div class="section">
<button class="ui-button" @click="toggleBridgeButton()">Toggle Bridge button</button>
<button class="ui-button" @click="openBridgeAppDrawer()">Open Bridge App Drawer</button>
<button class="ui-button" @click="toggleSystemWallpapers()">Toggle system wallpaper visibility</button>
<button class="ui-button" @click="toggleOverscrolling()">Toggle overscrolling</button>
<button class="ui-button" @click="reloadWindow()">Reload</button>
<br>
<small style="font-size:xx-small;color:white">Everything else can be configured through Bridge's Settings</small>
</div>
</template>

View file

@ -10,4 +10,6 @@ if (!window.Bridge) {
});
}
Bridge.requestSetBridgeTheme('system');
createApp(App).mount('#app')

View file

@ -1,7 +1,68 @@
// SCSS goes here
body {
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: #808080;
}
#applist {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-snap-stop: always;
}
#applist-wrapper {
width: 100%;
}
.applist-page {
scroll-snap-align: start;
display: flex;
flex-direction: row;
flex-wrap: wrap;
min-width: 100vw;
justify-content: flex-start;
align-content: flex-start;
padding-bottom: 10%;
padding-top: 5%;
& > * {
min-width: 25%; // 4 columns
margin-bottom: 5%;
}
}
#dock {
padding: 5%;
margin: 5%;
gap: 15px;
border-radius: 24px;
background-color: rgba(0,0,0,0.25);
border: 1px solid white;
display: flex;
justify-content: center;
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
.section {
padding: 5%;
margin: 5%;
margin-top: 0;
border-radius: 15px;
background-color: rgba(0,0,0,0.25);
border: 1px solid white;
width: 100%
}
.ui-button {
border: none;
border: 1px solid white;
border-radius: 6px;
padding: 2%;
background-color: rgba(0,0,0,0.5);
color: white;
margin: 1%;
}