Skip to content

Commit 7e40915

Browse files
authored
Merge pull request #185 from EducationalTools/184-feature-history
Add history
2 parents c0f5e78 + 082a380 commit 7e40915

2 files changed

Lines changed: 143 additions & 124 deletions

File tree

src/lib/components/play.svelte

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<script lang="ts">
2+
let { id } = $props();
3+
4+
// Components
5+
import { Button } from '$lib/components/ui/button/index.js';
6+
import { toast } from 'svelte-sonner';
7+
8+
// Icons
9+
import Refresh from 'lucide-svelte/icons/refresh-cw';
10+
import Fullscreen from 'lucide-svelte/icons/maximize';
11+
import OpenInNewTab from 'lucide-svelte/icons/external-link';
12+
import Share from 'lucide-svelte/icons/share';
13+
import Bookmark from 'lucide-svelte/icons/bookmark';
14+
15+
// App imports
16+
import { getGameById } from '$lib/gmaes';
17+
import { preferencesStore, favoritesStore, historyStore } from '$lib/stores';
18+
import { onMount } from 'svelte';
19+
20+
function openNewTab(url: string) {
21+
url = location.origin + url;
22+
var openedTab;
23+
if ($preferencesStore.open === 'tab') {
24+
openedTab = window.open('', '_blank');
25+
} else if ($preferencesStore.open === 'window') {
26+
openedTab = window.open('', '_blank');
27+
} else {
28+
$preferencesStore.open = 'tab';
29+
openNewTab(url);
30+
return;
31+
}
32+
if (!openedTab) return;
33+
const newDocument = openedTab.document;
34+
const style = newDocument.createElement('style');
35+
style.textContent = 'body, html { margin: 0; padding: 0; height: 100%; }';
36+
newDocument.head.appendChild(style);
37+
const iframe = newDocument.createElement('iframe');
38+
iframe.src = url;
39+
iframe.style.cssText = 'width: 100%; height: 100%; border: none;';
40+
newDocument.body.appendChild(iframe);
41+
}
42+
43+
const gmaedata = $derived(getGameById(id));
44+
45+
onMount(() => {
46+
let history = $historyStore;
47+
if (history.includes(id)) {
48+
history = history.filter((historyId) => historyId !== id);
49+
}
50+
51+
history.push(id);
52+
53+
historyStore.set(history);
54+
});
55+
</script>
56+
57+
<div class="flex h-full w-full flex-row gap-3 p-3">
58+
<iframe src={gmaedata?.url} frameborder="0" class="flex-grow rounded" title={gmaedata?.name}
59+
></iframe>
60+
61+
<div class="flex h-full w-72 flex-col">
62+
<h1 class="text-4xl font-bold">{gmaedata?.name}</h1>
63+
<p class="text-xl">{gmaedata?.description}</p>
64+
<div class="flex-grow"></div>
65+
<div class="flex flex-col gap-3">
66+
<Button
67+
variant="outline"
68+
onclick={() => {
69+
const iframe = document.querySelector('iframe');
70+
if (iframe && gmaedata?.url) {
71+
iframe.src = gmaedata.url;
72+
}
73+
}}
74+
>
75+
<Refresh class="h-6 w-6" />
76+
Reload
77+
</Button>
78+
<Button
79+
variant="outline"
80+
onclick={() => {
81+
document.querySelector('iframe')?.requestFullscreen();
82+
}}
83+
>
84+
<Fullscreen class="h-6 w-6" />
85+
Fullscreen
86+
</Button>
87+
<Button
88+
variant="outline"
89+
onclick={() => {
90+
if (gmaedata?.url) openNewTab(gmaedata.url);
91+
}}
92+
>
93+
<OpenInNewTab class="h-6 w-6" />
94+
New tab
95+
</Button>
96+
<Button
97+
variant="outline"
98+
onclick={() => {
99+
if (navigator.share) {
100+
navigator
101+
.share({
102+
text: window.location.href
103+
})
104+
.catch(() => {
105+
navigator.clipboard.writeText(window.location.href);
106+
toast.error('Failed to share link, copied to clipboard instead.');
107+
});
108+
} else {
109+
navigator.clipboard.writeText(window.location.href);
110+
toast.error('Failed to share link, copied to clipboard instead.');
111+
}
112+
}}
113+
>
114+
<Share class="h-6 w-6" />
115+
Share
116+
</Button>
117+
<Button
118+
variant="outline"
119+
onclick={() => {
120+
if (gmaedata?.id) {
121+
if ($favoritesStore.includes(gmaedata.id)) {
122+
$favoritesStore = $favoritesStore.filter((id) => id !== gmaedata.id);
123+
} else {
124+
$favoritesStore = [...$favoritesStore, gmaedata.id];
125+
}
126+
}
127+
}}
128+
>
129+
{#if gmaedata?.id && $favoritesStore.includes(gmaedata.id)}
130+
<Bookmark class="h-6 w-6 text-red-400" />
131+
Saved
132+
{:else}
133+
<Bookmark class="h-6 w-6" />
134+
Save
135+
{/if}
136+
</Button>
137+
</div>
138+
</div>
139+
</div>

src/routes/g/[id]/+page.svelte

Lines changed: 4 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,8 @@
11
<script lang="ts">
2-
// Framework imports
2+
import Play from '$lib/components/play.svelte';
33
import { page } from '$app/state';
4-
5-
// Components
6-
import { Button } from '$lib/components/ui/button/index.js';
7-
import { toast } from 'svelte-sonner';
8-
9-
// Icons
10-
import Refresh from 'lucide-svelte/icons/refresh-cw';
11-
import Fullscreen from 'lucide-svelte/icons/maximize';
12-
import OpenInNewTab from 'lucide-svelte/icons/external-link';
13-
import Share from 'lucide-svelte/icons/share';
14-
import Bookmark from 'lucide-svelte/icons/bookmark';
15-
16-
// App imports
17-
import { getGameById } from '$lib/gmaes';
18-
import { preferencesStore, favoritesStore } from '$lib/stores';
19-
20-
function openNewTab(url: string) {
21-
url = location.origin + url;
22-
var openedTab;
23-
if ($preferencesStore.open === 'tab') {
24-
openedTab = window.open('', '_blank');
25-
} else if ($preferencesStore.open === 'window') {
26-
openedTab = window.open('', '_blank');
27-
} else {
28-
$preferencesStore.open = 'tab';
29-
openNewTab(url);
30-
return;
31-
}
32-
if (!openedTab) return;
33-
const newDocument = openedTab.document;
34-
const style = newDocument.createElement('style');
35-
style.textContent = 'body, html { margin: 0; padding: 0; height: 100%; }';
36-
newDocument.head.appendChild(style);
37-
const iframe = newDocument.createElement('iframe');
38-
iframe.src = url;
39-
iframe.style.cssText = 'width: 100%; height: 100%; border: none;';
40-
newDocument.body.appendChild(iframe);
41-
}
42-
43-
const gmaedata = $derived(getGameById(page.params.id));
444
</script>
455

46-
<div class="flex h-full w-full flex-row gap-3 p-3">
47-
<iframe src={gmaedata?.url} frameborder="0" class="flex-grow rounded" title={gmaedata?.name}
48-
></iframe>
49-
50-
<div class="flex h-full w-72 flex-col">
51-
<h1 class="text-4xl font-bold">{gmaedata?.name}</h1>
52-
<p class="text-xl">{gmaedata?.description}</p>
53-
<div class="flex-grow"></div>
54-
<div class="flex flex-col gap-3">
55-
<Button
56-
variant="outline"
57-
onclick={() => {
58-
const iframe = document.querySelector('iframe');
59-
if (iframe && gmaedata?.url) {
60-
iframe.src = gmaedata.url;
61-
}
62-
}}
63-
>
64-
<Refresh class="h-6 w-6" />
65-
Reload
66-
</Button>
67-
<Button
68-
variant="outline"
69-
onclick={() => {
70-
document.querySelector('iframe')?.requestFullscreen();
71-
}}
72-
>
73-
<Fullscreen class="h-6 w-6" />
74-
Fullscreen
75-
</Button>
76-
<Button
77-
variant="outline"
78-
onclick={() => {
79-
if (gmaedata?.url) openNewTab(gmaedata.url);
80-
}}
81-
>
82-
<OpenInNewTab class="h-6 w-6" />
83-
New tab
84-
</Button>
85-
<Button
86-
variant="outline"
87-
onclick={() => {
88-
if (navigator.share) {
89-
navigator
90-
.share({
91-
text: window.location.href
92-
})
93-
.catch(() => {
94-
navigator.clipboard.writeText(window.location.href);
95-
toast.error('Failed to share link, copied to clipboard instead.');
96-
});
97-
} else {
98-
navigator.clipboard.writeText(window.location.href);
99-
toast.error('Failed to share link, copied to clipboard instead.');
100-
}
101-
}}
102-
>
103-
<Share class="h-6 w-6" />
104-
Share
105-
</Button>
106-
<Button
107-
variant="outline"
108-
onclick={() => {
109-
if (gmaedata?.id) {
110-
if ($favoritesStore.includes(gmaedata.id)) {
111-
$favoritesStore = $favoritesStore.filter((id) => id !== gmaedata.id);
112-
} else {
113-
$favoritesStore = [...$favoritesStore, gmaedata.id];
114-
}
115-
}
116-
}}
117-
>
118-
{#if gmaedata?.id && $favoritesStore.includes(gmaedata.id)}
119-
<Bookmark class="h-6 w-6 text-red-400" />
120-
Saved
121-
{:else}
122-
<Bookmark class="h-6 w-6" />
123-
Save
124-
{/if}
125-
</Button>
126-
</div>
127-
</div>
128-
</div>
6+
{#key page.params.id}
7+
<Play id={page.params.id} />
8+
{/key}

0 commit comments

Comments
 (0)