Skip to content
Merged
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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"scripts": {
"build": "node build.js",
"watch:src": "node watch.js",
"watch:dist": "mv3-hot-reload",
"watch:dist": "node lib/mv3-hot-reload/out/bin/mv3-hot-reload.js",
"dev": "concurrently yarn:watch:*",
"pretty-quick": "pretty-quick",
"precommit": "pretty-quick --staged",
"prepare": "husky install",
"preinstall": "cd ./lib/mv3-hot-reload && yarn install && ln -s ../mv3-hot-reload/out/bin/mv3-hot-reload.js ../../node_modules/.bin/mv3-hot-reload",
"preinstall": "cd ./lib/mv3-hot-reload && yarn install",
"zip": "npm-build-zip --source=dist --destination=build"
},
"author": "ujiro99",
Expand Down
Binary file added pages/public/chrome_web_store.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pages/public/favicon.ico
Binary file not shown.
62 changes: 61 additions & 1 deletion pages/scripts/fetch-ga-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,37 @@ async function runReport() {
},
],
dimensionFilter: {
orGroup: {
expressions: [
{
filter: {
fieldName: 'eventName',
stringFilter: {
value: 'command_hub_add',
matchType: 'EXACT',
},
},
},
{
filter: {
fieldName: 'eventName',
stringFilter: {
value: 'command_hub_star_add',
matchType: 'EXACT',
},
},
},
{
filter: {
fieldName: 'eventName',
stringFilter: {
value: 'command_hub_star_remove',
matchType: 'EXACT',
},
},
},
],
},
},
})

Expand All @@ -51,7 +75,43 @@ async function runReport() {
return acc
}, [])

fs.writeFileSync('./src/data/analytics.json', JSON.stringify(data, null, 2))
const groupped = data.reduce(
(acc, row) => {
switch (row.eventName) {
case 'command_hub_add':
acc.download.push({
eventId: row.eventId,
eventCount: row.eventCount,
})
break
case 'command_hub_star_add':
const r = acc.starred.find((a) => a.eventId === row.eventId) ?? {
eventId: row.eventId,
eventCount: 0,
}
r.eventCount += row.eventCount
acc.starred = acc.starred.filter((a) => a.eventId !== row.eventId)
acc.starred.push(r)
break
case 'command_hub_star_remove':
const r2 = acc.starred.find((a) => a.eventId === row.eventId) ?? {
eventId: row.eventId,
eventCount: 0,
}
r2.eventCount -= row.eventCount
acc.starred = acc.starred.filter((a) => a.eventId !== row.eventId)
acc.starred.push(r2)
break
}
return acc
},
{ download: [], starred: [], updated: Date.now() },
)

fs.writeFileSync(
'./src/data/analytics.json',
JSON.stringify(groupped, null, 2),
)
}

runReport().catch(console.error)
5 changes: 5 additions & 0 deletions pages/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,8 @@ body {
@apply bg-background text-foreground;
}
}

.starred svg {
@apply fill-amber-400;
@apply stroke-amber-400;
}
14 changes: 7 additions & 7 deletions pages/src/components/CommandForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const STORAGE_KEY = 'CommandShareFormData'

let onChagneSearchUrlTO = 0

type CommandMessage = Omit<Command, 'download' | 'thanks'>
type CommandMessage = Omit<Command, 'download' | 'star'>

const toMessages = (data: FormValues) => {
const msgObj = toCommand(data)
Expand Down Expand Up @@ -276,7 +276,7 @@ function InputForm(props: InputProps) {
}
}, [setValue])

form.watch((data) => {
form.watch((data: FormValues) => {
if (!data.title && !data.searchUrl) {
return
}
Expand Down Expand Up @@ -596,7 +596,7 @@ function InputForm(props: InputProps) {
const Item = ({ label, value }: { label: string; value: string }) => (
<div className="flex items-center">
<label className="w-2/6 text-sm font-medium">{label}</label>
<div className="w-4/6 font-[family-name:var(--font-geist-mono)] text-sm leading-relaxed overflow-scroll whitespace-nowrap inline-block">
<div className="w-4/6 font-[family-name:var(--font-geist-mono)] text-sm leading-relaxed overflow-x-auto whitespace-nowrap inline-block">
<span>{value}</span>
</div>
</div>
Expand Down Expand Up @@ -672,7 +672,7 @@ function SendingForm() {
送信中...
</DialogDescription>
<Image
src="bars-scale-middle.svg"
src="/bars-scale-middle.svg"
alt="Uploading..."
width={30}
height={30}
Expand Down Expand Up @@ -703,14 +703,14 @@ function CompleteForm() {
<br />
</p>
<Image
src="engineer_suit_simple.png"
src="/engineer_suit_simple.png"
alt="Engineer"
width={100}
height={100}
className="rounded-full bg-stone-200 ml-3"
className="rounded-full bg-stone-200 ml-3 h-[100px]"
style={
{
objectViewBox: 'inset(-22px 56px 360px 283px)',
objectViewBox: 'inset(-5px 12px 65px 52px)',
} as React.CSSProperties
}
/>
Expand Down
2 changes: 1 addition & 1 deletion pages/src/components/CommandShare.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { CommandForm } from '@/components/CommandForm'
export function CommandShare(): JSX.Element {
return (
<Dialog>
<DialogTrigger className="flex items-center px-4 py-1.5 h-10 rounded-full bg-stone-700 text-primary-foreground shadow hover:bg-primary/90 outline-none">
<DialogTrigger className="flex items-center px-4 py-1.5 h-10 rounded-full bg-stone-700 text-primary-foreground shadow hover:bg-primary/90 outline-none transition">
<ArrowUpToLine size={18} />
<span className="ml-1.5 font-semibold">コマンド共有</span>
</DialogTrigger>
Expand Down
5 changes: 3 additions & 2 deletions pages/src/components/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react'
import NextImage from 'next/image'
import { cn } from '@/lib/utils'

import nextConfig from '../../next.config.mjs'
const BASE_PATH = nextConfig.basePath || ''
Expand All @@ -16,10 +17,10 @@ type Props = {
function Image(props: Props): JSX.Element {
let { src } = props
if (src.startsWith('/')) {
src = `${BASE_PATH}/${props.src}`
src = `${BASE_PATH}${props.src}`
return (
<NextImage
className="dark:invert"
className={cn('dark:invert', props.className)}
src={src}
alt={`${props.alt}`}
width={`${props.width ?? 20}`}
Expand Down
56 changes: 40 additions & 16 deletions pages/src/components/ListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import Link from 'next/link'
import { ArrowDownToLine } from 'lucide-react'
import { ArrowDownToLine, Check, Star } from 'lucide-react'
import { Image } from '@/components/Image'
import { Tag } from '@/components/Tag'
import type { Command } from '@/types'
Expand All @@ -14,8 +14,8 @@ export function ListItem(props: Props): JSX.Element {
const { cmd } = props
return (
<>
<div className="text-left flex flex-row">
<div className="flex-1">
<div className="text-left flex flex-row items-center gap-1">
<div className="flex-1 overflow-hidden space-y-1">
<p className="text-lg flex flex-row">
<Image
src={cmd.iconUrl}
Expand All @@ -24,29 +24,53 @@ export function ListItem(props: Props): JSX.Element {
/>
{cmd.title}
</p>
<p className="text-base text-sm text-stone-500">{cmd.searchUrl}</p>
<p className="text-base text-sm text-stone-500 truncate">
{cmd.searchUrl}
</p>
<p className="text-base">{cmd.description}</p>
</div>
<div className="flex items-center text-stone-600">
<div>
<p
className="hidden px-2 py-0.5 bg-stone-200 rounded-md"
<div className="flex gap-1">
<div className="flex items-center text-stone-600">
<div>
<p className="hidden" data-id={cmd.id}>
<Check className="p-1 stroke-sky-500" size={28} />
</p>
<button
className="hidden hover:bg-stone-200 rounded transition"
data-id={cmd.id}
data-command={cmd2text(cmd)}
data-gtm-click="install"
>
<ArrowDownToLine className="p-1" size={28} />
</button>
</div>
<span
className="pl-0.5 p-1 select-none"
data-id={cmd.id}
data-download-count={cmd.download}
>
<span className="select-none">Installed</span>
</p>
{cmd.download.toLocaleString()}
</span>
</div>
<div className="flex items-center text-stone-600">
<button
className="hidden hover:bg-stone-200 rounded"
data-id={cmd.id}
data-command={cmd2text(cmd)}
className="hover:bg-stone-200 rounded transition duration-50"
data-star-id={cmd.id}
data-gtm-click="star"
>
<ArrowDownToLine className="p-1" size={28} />
<Star className="p-1 transition" size={28} />
</button>
<span
className="pl-0.5 p-1 select-none"
data-star-id={cmd.id}
data-star-count={cmd.star}
>
{cmd.star.toLocaleString()}
</span>
</div>
<span className="ml-2 p-1 pl-0 select-none">{cmd.download}</span>
</div>
</div>
<ul className="mt-2 flex gap-2">
<ul className="mt-2 flex gap-2 flex-wrap">
{cmd.tags.map((tag) => (
<li key={tag.id}>
<Link href={`/tag/${tag.name}`}>
Expand Down
10 changes: 8 additions & 2 deletions pages/src/components/layout/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { updated } from '@/data/analytics.json'

export function Footer(): JSX.Element {
const updatedDate = new Date(updated)
return (
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
© 2024 Selection Command
<footer className="row-start-3 flex flex-col gap-3 items-center">
<p className="text-stone-500 text-sm" data-updated={updated}>
Last Updated: {updatedDate.toLocaleDateString()}
</p>
<p className="text-stone-500">© 2024 Selection Command</p>
</footer>
)
}
29 changes: 21 additions & 8 deletions pages/src/components/layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
import Link from 'next/link'
import { Image } from '@/components/Image'
import { MousePointer } from 'lucide-react'
import css from './Header.module.css'
import commonCss from '@/lib/common.module.css'

export function Header(): JSX.Element {
return (
<Link href="/" className={commonCss.hover}>
<header className="flex items-center gap-1.5 text-3xl font-[family-name:var(--font-geist-mono)] font-medium">
Selection{' '}
<span className="bg-[#1597C9]/20 px-2 py-0.5 rounded-lg">Command</span>
<span className="font-extralight ml-1">Hub</span>
<MousePointer className={css.mouse} size={26} />
</header>
</Link>
<div>
<Link href="/" className={commonCss.hover}>
<header className="flex items-center gap-1.5 text-3xl font-[family-name:var(--font-geist-mono)] font-medium">
Selection{' '}
<span className="bg-[#1597C9]/20 px-2 py-0.5 rounded-lg">
Command
</span>
<span className="font-extralight ml-1">Hub</span>
<MousePointer className={css.mouse} size={26} />
</header>
</Link>
<a
href="https://chromewebstore.google.com/detail/selection-command/nlnhbibaommoelemmdfnkjkgoppkohje"
target="_blank"
className="fixed top-2 right-2 bg-white border border-stone-200 rounded-lg shadow-md transition duration-200 hover:shadow-lg"
data-gtm-click="chrome-web-store"
>
<Image src="/chrome_web_store.png" alt="Chrome Web Store" width={200} />
</a>
</div>
)
}
50 changes: 28 additions & 22 deletions pages/src/data/analytics.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
[
{
"eventName": "command_hub_add",
"eventId": "f5492254-4d6c-5924-860f-c8b668a76d7a",
"eventCount": 4
},
{
"eventName": "command_hub_add",
"eventId": "020d116e-5956-5274-b785-b7f4d7377a52",
"eventCount": 1
},
{
"eventName": "command_hub_add",
"eventId": "33cd4e4c-a7cf-593f-b2c7-bf8743882aae",
"eventCount": 1
},
{
"eventName": "command_hub_add",
"eventId": "f3254d62-2f77-528c-b7bd-6260c67802ec",
"eventCount": 1
}
]
{
"download": [
{
"eventId": "f5492254-4d6c-5924-860f-c8b668a76d7a",
"eventCount": 4
},
{
"eventId": "020d116e-5956-5274-b785-b7f4d7377a52",
"eventCount": 1
},
{
"eventId": "33cd4e4c-a7cf-593f-b2c7-bf8743882aae",
"eventCount": 1
},
{
"eventId": "f3254d62-2f77-528c-b7bd-6260c67802ec",
"eventCount": 1
}
],
"starred": [
{
"eventId": "f5492254-4d6c-5924-860f-c8b668a76d7a",
"eventCount": 2
}
],

"updated": 1734748334762
}
Loading