Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reconfigure to modern WarpDrive #1

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
/.node_modules.ember-try/

/tmp/
generate.mjs
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Install Node
uses: actions/setup-node@v4
with:
Expand Down
60 changes: 60 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# This is a basic workflow to help you get started with Actions

name: Deploy Github Pages

concurrency:
group: "gh-pages"
cancel-in-progress: true

# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the "master" branch
push:
branches: [ "master" ]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v4
- name: Install Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm run build
# - name: CompressFiles
# uses: runspired/ghaction-CompressFiles@master
# with:
# path: dist
# extensions: '.js,.css,.html'
# tools: 'brotli'
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: dist
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
5 changes: 5 additions & 0 deletions app/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@
font-family: "Pixelify Sans", system-ui, sans-serif;
}
}

div.data-pokemon-thumbnail-loading {
width: 100%;
aspect-ratio: 1 / 1;
}
6 changes: 6 additions & 0 deletions app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers';
import config from 'ember-polaris-pokedex/config/environment';
import './app.css';
import { setBuildURLConfig } from '@ember-data/request-utils';

setBuildURLConfig({
host: window.location.origin,
namespace: 'api',
});

// @ts-expect-error: no types for define
let d = window.define;
Expand Down
6 changes: 3 additions & 3 deletions app/components/pokemon-details.gts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Component from '@glimmer/component';
import type PokemonModel from 'ember-polaris-pokedex/models/pokemon';
import type { Pokemon } from 'ember-polaris-pokedex/schemas/pokemon';
import PokemonTypeBadge from 'ember-polaris-pokedex/components/pokemon-type-badge';
import PokemonEvolutionNav from 'ember-polaris-pokedex/components/pokemon-evolution-nav';

export default class PokemonDetails extends Component<{
Args: { pokemon: PokemonModel; allPokemon: PokemonModel[] };
Args: { pokemon: Pokemon };
}> {
<template>
<div
Expand Down Expand Up @@ -36,7 +36,7 @@ export default class PokemonDetails extends Component<{
</div>
</div>

<PokemonEvolutionNav @pokemon={{@pokemon}} @allPokemon={{@allPokemon}} />
<PokemonEvolutionNav @pokemon={{@pokemon}} />

{{! prettier-ignore }}
<style>
Expand Down
26 changes: 17 additions & 9 deletions app/components/pokemon-evolution-nav.gts
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import Component from '@glimmer/component';
import { get } from '@ember/helper';
import type PokemonModel from 'ember-polaris-pokedex/models/pokemon';
import type { Pokemon } from 'ember-polaris-pokedex/schemas/pokemon';
import type RouterService from '@ember/routing/router-service';
import { service } from '@ember/service';
import { fn } from '@ember/helper';
import { on } from '@ember/modifier';
import { preloadImage } from 'ember-polaris-pokedex/components/pokemon-grid-item';
import type { ImageFetch } from '@warp-drive/experiments/image-fetch';

export function getPokemonById(pokemons: PokemonModel[], id: string) {
return pokemons.find((pokemon) => pokemon.id!.toString() === id);
export function getPokemonById(pokemons: Pokemon[], id: string) {
return pokemons.find((pokemon) => pokemon.id === id);
}

// https://raw.githubusercontent.com/IgnaceMaes/pokemon-data.json/master/images/pokedex/hires/005.png
function getHiresImageForId(id: string) {
return `https://raw.githubusercontent.com/IgnaceMaes/pokemon-data.json/master/images/pokedex/hires/${id.padStart(
3,
'0',
)}.png`;
}

export default class PokemonEvolutionNav extends Component<{
Args: { pokemon: PokemonModel; allPokemon: PokemonModel[] };
Args: { pokemon: Pokemon };
}> {
@service declare router: RouterService;
@service declare images: ImageFetch;

transitionToPokemonDetails = (
pokemonId: string,
Expand All @@ -37,10 +46,9 @@ export default class PokemonEvolutionNav extends Component<{
};

preloadImageForPokemonId = (pokemonId: string) => {
const pokemon = getPokemonById(this.args.allPokemon, pokemonId);
if (pokemon) {
preloadImage(pokemon.image.hires);
}
const url = getHiresImageForId(pokemonId);
this.images.load(url);
// preloadImage(getHiresImageForId(pokemonId));
};

<template>
Expand Down
48 changes: 37 additions & 11 deletions app/components/pokemon-grid-item.gts
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { fn } from '@ember/helper';
import { on } from '@ember/modifier';
import Component from '@glimmer/component';
import type PokemonModel from 'ember-polaris-pokedex/models/pokemon';
import type { Pokemon } from 'ember-polaris-pokedex/schemas/pokemon';
import { service } from '@ember/service';
import type RouterService from '@ember/routing/router-service';
import type { ImageFetch } from '@warp-drive/experiments/image-fetch';
import { cached } from '@glimmer/tracking';
import { getPromiseState } from '@warp-drive/ember';

export function preloadImage(imageUrl: string) {
const img = new Image();
img.src = imageUrl;
}

interface PokemonSignature {
Args: { pokemon: PokemonModel };
Args: { pokemon: Pokemon };
}

export default class PokemonGridItem extends Component<PokemonSignature> {
@service declare router: RouterService;
@service declare images: ImageFetch;

transitionToPokemonDetails = (pokemon: PokemonModel, event: MouseEvent) => {
transitionToPokemonDetails = (pokemon: Pokemon, event: MouseEvent) => {
// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
this.router.transitionTo('pokemon.pokemon', pokemon.id?.toString());
Expand All @@ -38,20 +42,42 @@ export default class PokemonGridItem extends Component<PokemonSignature> {
});
};

preloadImage = (imageUrl: string) => {
this.images.load(imageUrl);
};

@cached
get thumbnailRequest() {
return this.images.load(this.args.pokemon.image.thumbnail);
}

@cached
get thumbnailUrl() {
const state = getPromiseState(this.thumbnailRequest);
if (state.isError || state.isPending) {
return null;
}
return state.result;
}

<template>
<button
type='button'
class='revealing-image group flex cursor-pointer flex-col items-center rounded-xl bg-gradient-to-br from-pink-100 to-yellow-100 p-4 shadow transition-shadow hover:shadow-md'
{{on 'pointerenter' (fn preloadImage @pokemon.image.hires)}}
{{on 'pointerenter' (fn this.preloadImage @pokemon.image.hires)}}
{{on 'click' (fn this.transitionToPokemonDetails @pokemon)}}
>
<img
data-pokemon-thumbnail
class='block aspect-square w-full p-4 transition-transform group-hover:scale-125 group-hover:drop-shadow-xl'
loading='lazy'
src={{@pokemon.image.thumbnail}}
alt='{{@pokemon.name.english}} thumbnail'
/>
{{#if this.thumbnailUrl}}
<img
data-pokemon-thumbnail
class='block aspect-square w-full p-4 transition-transform group-hover:scale-125 group-hover:drop-shadow-xl'
loading='lazy'
src={{this.thumbnailUrl}}
alt='{{@pokemon.name.english}} thumbnail'
/>
{{else}}
<div class='data-pokemon-thumbnail-loading'></div>
{{/if}}
<span class='mt-4 text-lg font-medium'>{{@pokemon.name.english}}</span>
</button>
</template>
Expand Down
2 changes: 1 addition & 1 deletion app/components/pokemon-type-badge.gts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PokemonType } from 'ember-polaris-pokedex/models/pokemon';
import type { PokemonType } from 'ember-polaris-pokedex/schemas/pokemon';
import { get } from '@ember/helper';
import type { TOC } from '@ember/component/template-only';
import {
Expand Down
34 changes: 34 additions & 0 deletions app/data-worker/data-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Store from '@ember-data/store';
import RequestManager from '@ember-data/request';
import Fetch from '@ember-data/request/fetch';
import JSONAPICache from '@ember-data/json-api';

import { DataWorker, CacheHandler } from '@warp-drive/experiments/data-worker';
import type { CacheCapabilitiesManager } from '@ember-data/store/types';
import { CachePolicy } from '@ember-data/request-utils';
import { SchemaService } from '@warp-drive/schema-record/schema';
import { register } from '../schemas/pokemon';
import { PokemonHandler } from '../utils/handlers';

class WorkerStore extends Store {
requestManager = new RequestManager()
.use([PokemonHandler, Fetch])
.useCache(CacheHandler);

lifetimes = new CachePolicy({
apiCacheHardExpires: 1000 * 60 * 60 * 48, // 48 hours
apiCacheSoftExpires: 1000 * 60 * 60, // 1 hour
});

createCache(capabilities: CacheCapabilitiesManager) {
return new JSONAPICache(capabilities);
}

createSchemaService() {
const schema = new SchemaService();
register(schema);
return schema;
}
}

new DataWorker(WorkerStore, { persisted: true });
3 changes: 3 additions & 0 deletions app/data-worker/image-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ImageWorker } from '@warp-drive/experiments/image-worker';

new ImageWorker();
8 changes: 8 additions & 0 deletions app/data-worker/loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { WorkerFetch } from '@warp-drive/experiments/worker-fetch';

export const WorkerHandler = new WorkerFetch(
new SharedWorker(new URL('./data-worker.ts', import.meta.url), {
name: 'DataWorker',
type: 'module',
}),
);
68 changes: 0 additions & 68 deletions app/models/pokemon.ts

This file was deleted.

8 changes: 5 additions & 3 deletions app/routes/application.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import Route from '@ember/routing/route';
import { service } from '@ember/service';
import { query } from '@ember-data/rest/request';
import { query } from '@ember-data/json-api/request';
import type StoreService from '@ember-data/store';
import PokemonModel from 'ember-polaris-pokedex/models/pokemon';
import type { Pokemon } from 'ember-polaris-pokedex/schemas/pokemon';

export default class ApplicationRoute extends Route {
@service declare store: StoreService;

model() {
return {
pokemonRequest: this.store.request(query<PokemonModel>('pokemon')),
pokemonRequest: this.store.request(
query<Pokemon>('pokemon', {}, { resourcePath: 'pokemon/list.json' }),
),
};
}
}
Loading