Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ios/App/App.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions ios/App/Podfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
PODS:
- Capacitor (6.1.2):
- CapacitorCordova
- CapacitorCordova (6.1.2)

DEPENDENCIES:
- "Capacitor (from `../../node_modules/@capacitor/ios`)"
- "CapacitorCordova (from `../../node_modules/@capacitor/ios`)"

EXTERNAL SOURCES:
Capacitor:
:path: "../../node_modules/@capacitor/ios"
CapacitorCordova:
:path: "../../node_modules/@capacitor/ios"

SPEC CHECKSUMS:
Capacitor: 679f9673fdf30597493a6362a5d5bf233d46abc2
CapacitorCordova: f48c89f96c319101cd2f0ce8a2b7449b5fb8b3dd

PODFILE CHECKSUM: 8ab55909c5de2b217f9841e5e5b329f5ec901553

COCOAPODS: 1.15.2
6 changes: 6 additions & 0 deletions src/lib/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/lib/components/Ball.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
</script>

{#await getImgUrl(pocketed) then src}
<img class="w-full max-h-[min(100%,6rem)] m-auto" {src} alt="{ball.number} ball" />
<img class="w-full max-h-[min(100%,6rem)] m-auto" {src} alt="{ball.number} ball {ball.color}" />
{/await}
32 changes: 22 additions & 10 deletions src/lib/components/Hamburger.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
import { goto } from '$app/navigation';

type OptionTitle = 'Score Sheet' | 'Save Game' | 'Settings' | 'End Game';
type Option = { title: OptionTitle; icon: ComponentType; onClick?: () => void };
type Option = { title: OptionTitle; icon: ComponentType; onClick?: () => void; href?: string };

const hamburgerOptions: Option[] = [
{ title: 'Score Sheet', icon: ScoreSheetIcon },
{ title: 'Score Sheet', icon: ScoreSheetIcon, href: '/score-sheet' },
{ title: 'Save Game', icon: SaveIcon },
{ title: 'Settings', icon: SettingsIcon },
{
Expand Down Expand Up @@ -76,14 +76,26 @@
transition:fade={{ duration: 300 }}
>
{#each hamburgerOptions as option, i}
<button
class="flex w-full gap-2 py-2 px-6 bg-white text-black hover:bg-slate-300"
style:border-bottom={i < hamburgerOptions.length - 1 ? '1px solid black' : ''}
on:click={() => option.onClick?.() ?? handleOptionClick(option.title)}
>
<svelte:component this={option.icon} />
{option.title}
</button>
{#if option.href}
<a
class="flex w-full gap-2 py-2 px-6 bg-white text-black hover:bg-slate-300"
style:border-bottom={i < hamburgerOptions.length - 1 ? '1px solid black' : ''}
href={option.href}
on:click={handleClose}
>
<svelte:component this={option.icon} />
{option.title}
</a>
{:else}
<button
class="flex w-full gap-2 py-2 px-6 bg-white text-black hover:bg-slate-300"
style:border-bottom={i < hamburgerOptions.length - 1 ? '1px solid black' : ''}
on:click={() => option.onClick?.() ?? handleOptionClick(option.title)}
>
<svelte:component this={option.icon} />
{option.title}
</button>
{/if}
Comment on lines +79 to +98
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use svelte:element to reduce duplication

{/each}
</div>
{/if}
60 changes: 60 additions & 0 deletions src/lib/components/InfoBox.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script lang="ts">
import { BALL_COLORS } from '$lib/common/ball';
import type { Player, Game } from '$lib/types';
import { tweened } from 'svelte/motion';

export let player: Player | null = null;
export let game: Game;
export let playerNumber: number = 0;

export let isScoreSheet: boolean = false;

const transparency = tweened();

$: isActive = isScoreSheet ? isScoreSheet : game.currentPlayer === player;
$: border = player ? (isActive ? player?.color.border : 'border-[#28282C]') : 'border-[#28282C]';
$: fromStop = player
? player?.color.gradient.stops[0]
: BALL_COLORS[BALL_COLORS.length - 1].gradient.stops[0];
$: $transparency = isActive ? 70 : 0;
</script>

<!-- the color-mix below is a trick to add opacity to the given color -->
<div
class="player-score portrait:w-1/2 landscape:h-1/2 border-2 max-h-60 px-2 py-1 border-solid rounded-xl grid grid-rows-[auto_1fr_auto] grid-cols-1 landscape:grid-rows-[min-content_min-content] landscape:grid-cols-2 gap-y-2 content-between {border} bg-[#28282C] overflow-clip"
class:radial-to-tr={playerNumber === 0}
class:radial-to-bl={playerNumber === 1}
style:--from-stop="var({fromStop})"
style:--transparency="{$transparency}%"
style:background-image={'radial-gradient(var(--position), color-mix(in srgb, var(--from-stop) var(--transparency), transparent), #1F2026 var(--end-stop))'}
>
<slot />
</div>

<style>
.player-score {
background-size: 150% 150%;
animation: Animation 8s ease infinite alternate;
}
@keyframes Animation {
0% {
background-position: 0% 0%;
}
50% {
background-position: 91% 100%;
}
100% {
background-position: 0% 0%;
}
}
.radial-to-bl {
--position: circle at left 70% top 0%;
--end-stop: 80%;
animation: Animation 8s ease infinite alternate-reverse;
}

.radial-to-tr {
--position: circle at right 70% bottom 0%;
--end-stop: 100%;
}
</style>
6 changes: 6 additions & 0 deletions src/lib/components/icons/EditIcon.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"
><path
fill="currentColor"
d="M6 2c-1.11 0-2 .89-2 2v16a2 2 0 0 0 2 2h4v-1.91L12.09 18H6v-2h8.09l2-2H6v-2h12.09L20 10.09V8l-6-6zm7 1.5L18.5 9H13zm7.15 9.5a.55.55 0 0 0-.4.16l-1.02 1.02l2.09 2.08l1.02-1.01c.21-.22.21-.58 0-.79l-1.3-1.3a.54.54 0 0 0-.39-.16m-2.01 1.77L12 20.92V23h2.08l6.15-6.15z"
/></svg
>
6 changes: 6 additions & 0 deletions src/lib/components/icons/RightArrow.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"
><path
fill="#FFF"
d="M27.317 18.846c2.242-1.235 2.242-4.457 0-5.693L7.82 2.403C5.653 1.21 3 2.777 3 5.25v21.492c0 2.473 2.652 4.04 4.818 2.846z"
/></svg
>
73 changes: 25 additions & 48 deletions src/lib/components/nine-ball/PlayerStats.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,55 @@
import { fly } from 'svelte/transition';
import TimeoutIcon from '../icons/TimeoutIcon.svelte';
import ShieldIcon from '../icons/ShieldIcon.svelte';
import InfoBox from '../InfoBox.svelte';
import type { Game, Player } from '$lib/types';
import { tweened } from 'svelte/motion';
import type { NineBallRack } from '$lib/nine-ball';

export let player: Player;
export let game: Game;
export let playerNumber: number;
export let isScoreSheet: boolean = false;
export let rack: NineBallRack | null = null;

const transparency = tweened();
function getTimeoutsUsed(num: number) {
if (num) return 0;
return 1;
}

$: timeouts = game.currentRack.timeouts[playerNumber];
$: isActive = game.currentPlayer === player;
$: border = isActive ? player.color.border : 'border-[#28282C]';
$: $transparency = isActive ? 70 : 0;
$: timeouts = isScoreSheet
? rack
? game.totalTimeoutsUsed[playerNumber]
: getTimeoutsUsed(game.currentRack.timeouts[playerNumber])
: game.currentRack.timeouts[playerNumber];
$: score = rack ? rack.scores[playerNumber] : player.score;
$: safeties = rack ? rack.safeties[playerNumber] : player.safeties;
</script>

<!-- the color-mix below is a trick to add opacity to the given color -->
<div
class="player-score portrait:w-1/2 landscape:h-1/2 border-2 max-h-60 px-2 py-1 border-solid rounded-xl grid grid-rows-[auto_1fr_auto] grid-cols-1 landscape:grid-rows-[min-content_min-content] landscape:grid-cols-2 gap-y-2 content-between {border} bg-[#28282C] overflow-clip"
class:radial-to-tr={playerNumber === 0}
class:radial-to-bl={playerNumber === 1}
style:--transparency="{$transparency}%"
style:--from-stop="var({player.color.gradient.stops[0]})"
style:background-image={'radial-gradient(var(--position), color-mix(in srgb, var(--from-stop) var(--transparency), transparent), #1F2026 var(--end-stop))'}
>
<InfoBox {game} {player} {playerNumber} {isScoreSheet}>
<div class="flex landscape:block w-full justify-between overflow-hidden">
<div class="font-large truncate mr-2">{player.name}</div>
<div class="font-light text-secondary whitespace-nowrap">level {player.handicap}</div>
</div>
<div
class="score font-light text-5xl relative overflow-hidden stack text-center landscape:justify-end row-span-2 self-center landscape:text-7xl landscape:mx-4"
>
{#key player.score}
{#key score}
<div in:fly={{ y: '100%' }} out:fly={{ y: '-100%' }}>
{player.score}
{score}
</div>
{/key}
</div>

{#if isScoreSheet}
<span>Totals:</span>
{/if}
<div class="w-full flex portrait:justify-between landscape:gap-2">
<div class="flex gap-2 min-w-10 items-center">
<ShieldIcon class="w-4" variant="filled" />
<div class="stack relative">
{#key player.safeties}
{#key safeties}
<div in:fly={{ y: '80%' }} out:fly={{ y: '-80%', duration: 50 }}>
{player.safeties}
{safeties}
</div>
{/key}
</div>
Expand All @@ -65,32 +70,4 @@
<span class="text-primary">{player.scoreRequired}</span>
</div>
</div>
</div>

<style>
.player-score {
background-size: 150% 150%;
animation: Animation 8s ease infinite alternate;
}
@keyframes Animation {
0% {
background-position: 0% 0%;
}
50% {
background-position: 91% 100%;
}
100% {
background-position: 0% 0%;
}
}
.radial-to-bl {
--position: circle at left 70% top 0%;
--end-stop: 80%;
animation: Animation 8s ease infinite alternate-reverse;
}

.radial-to-tr {
--position: circle at right 70% bottom 0%;
--end-stop: 100%;
}
</style>
</InfoBox>
32 changes: 32 additions & 0 deletions src/lib/components/score-sheet/Accordion.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import InfoBox from './InfoBox.svelte';
import { slide } from 'svelte/transition';
import RightArrow from '../icons/RightArrow.svelte';
let isOpen = false;
function toggle() {
isOpen = !isOpen;
}
</script>

<InfoBox transparency={70}>
<div class="flex justify-between items-center">
<slot name="header" />
<div class="transition-opacity duration-300 {isOpen ? 'opacity-0' : 'opacity-100'}">
<slot name="points" />
</div>
<button on:click={toggle} class="transition scale-50" class:rotate={isOpen}>
<RightArrow />
</button>
</div>
{#if isOpen}
<div transition:slide>
<slot name="info" />
</div>
{/if}
</InfoBox>

<style>
.rotate {
transform: rotate(90deg) scale(0.5);
}
</style>
38 changes: 38 additions & 0 deletions src/lib/components/score-sheet/InfoBox.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script lang="ts">
import { BALL_COLORS } from '$lib/common/ball';
export let transparency: number;
</script>

<div
class="player-score radial-to-bl w-full border-2 px-2 py-1 border-solid rounded-xl grid grid-cols-1 gap-y-2 bg-[#28282C] border-[#28282C] overflow-clip"
style:--from-stop="var({BALL_COLORS[BALL_COLORS.length - 1].gradient.stops[0]})"
style:--transparency="{transparency}%"
style:background-image={'radial-gradient(var(--position), color-mix(in srgb, var(--from-stop) var(--transparency), transparent), #1F2026 var(--end-stop))'}
>
<slot />
</div>

<style>
.player-score {
background-size: 150% 150%;
animation: Animation 8s ease infinite alternate;
}

.radial-to-bl {
--position: circle at left 70% top 0%;
--end-stop: 80%;
animation: Animation 8s ease infinite alternate-reverse;
}

@keyframes Animation {
0% {
background-position: 0% 0%;
}
50% {
background-position: 91% 100%;
}
100% {
background-position: 0% 0%;
}
}
</style>
9 changes: 9 additions & 0 deletions src/lib/components/score-sheet/InfoLine.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script lang="ts">
export let title: string;
export let amount: string | number;
</script>

<div class="m-auto w-1/2 flex justify-between">
<span>{title}:</span>
<span>{amount}</span>
</div>
8 changes: 8 additions & 0 deletions src/lib/components/score-sheet/RackAtGlance.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script lang="ts">
export let rack;
</script>

<div class="flex gap-4">
<span>Rack Points: {rack.scores[0]}-{rack.scores[1]}</span>
<span>Innings: {rack.innings}</span>
</div>
Loading