refactor: update titles and descriptions to use double quotes for consistency
fix: add newlines and formatting improvements in blog posts refactor: update import paths to use alias for better readability style: update global CSS to use double quotes for consistency chore: update tsconfig to include path aliasing for cleaner imports
This commit is contained in:
parent
05dfaed605
commit
33083907fb
22 changed files with 618 additions and 490 deletions
|
|
@ -1,11 +1,11 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from "astro/config";
|
||||||
|
|
||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [tailwindcss()]
|
plugins: [tailwindcss()],
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
62
package-lock.json
generated
62
package-lock.json
generated
|
|
@ -13,7 +13,9 @@
|
||||||
"tailwindcss": "^4.1.18"
|
"tailwindcss": "^4.1.18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.19"
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"prettier-plugin-astro": "^0.14.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@astrojs/compiler": {
|
"node_modules/@astrojs/compiler": {
|
||||||
|
|
@ -4438,6 +4440,37 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prettier": {
|
||||||
|
"version": "3.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
|
||||||
|
"integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"prettier": "bin/prettier.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prettier-plugin-astro": {
|
||||||
|
"version": "0.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier-plugin-astro/-/prettier-plugin-astro-0.14.1.tgz",
|
||||||
|
"integrity": "sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@astrojs/compiler": "^2.9.1",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"sass-formatter": "^0.7.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.15.0 || >=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prismjs": {
|
"node_modules/prismjs": {
|
||||||
"version": "1.30.0",
|
"version": "1.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
|
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
|
||||||
|
|
@ -4761,6 +4794,23 @@
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/s.color": {
|
||||||
|
"version": "0.0.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/s.color/-/s.color-0.0.15.tgz",
|
||||||
|
"integrity": "sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/sass-formatter": {
|
||||||
|
"version": "0.7.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-formatter/-/sass-formatter-0.7.9.tgz",
|
||||||
|
"integrity": "sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"suf-log": "^2.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sax": {
|
"node_modules/sax": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz",
|
||||||
|
|
@ -4926,6 +4976,16 @@
|
||||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/suf-log": {
|
||||||
|
"version": "2.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/suf-log/-/suf-log-2.5.3.tgz",
|
||||||
|
"integrity": "sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"s.color": "0.0.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/svgo": {
|
"node_modules/svgo": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"build": "astro build",
|
"build": "astro build",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"astro": "astro"
|
"astro": "astro",
|
||||||
|
"format": "prettier --write ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
|
|
@ -14,6 +15,8 @@
|
||||||
"tailwindcss": "^4.1.18"
|
"tailwindcss": "^4.1.18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.19"
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"prettier-plugin-astro": "^0.14.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
import NavLink from "./NavLink.astro";
|
import NavLink from "@/components/NavLink.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<header class="py-4 text-black dark:text-white w-full">
|
<header class="py-4 text-black dark:text-white w-full">
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
---
|
---
|
||||||
import { Image } from 'astro:assets';
|
import { Image } from 'astro:assets';
|
||||||
import profileImage from "../assets/images/profile.jpg";
|
import profileImage from "@/assets/images/profile.jpg";
|
||||||
import socialEmail from "../assets/images/social-email.svg";
|
import socialEmail from "@/assets/images/social-email.svg";
|
||||||
import socialFacebook from "../assets/images/social-facebook.svg";
|
import socialFacebook from "@/assets/images/social-facebook.svg";
|
||||||
import socialGithub from "../assets/images/social-github.svg";
|
import socialGithub from "@/assets/images/social-github.svg";
|
||||||
import socialLinkedIn from "../assets/images/social-linkedin.svg";
|
import socialLinkedIn from "@/assets/images/social-linkedin.svg";
|
||||||
import socialX from "../assets/images/social-x.svg";
|
import socialX from "@/assets/images/social-x.svg";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex flex-col min-h-full items-center justify-center">
|
<div class="flex flex-col min-h-full items-center justify-center">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'CRDT - Conflict Free Replicated Data Types'
|
title: "CRDT - Conflict Free Replicated Data Types"
|
||||||
description: 'A brief intro to Conflict Free Replicated Data Types'
|
description: "A brief intro to Conflict Free Replicated Data Types"
|
||||||
date: 2025-02-24T09:58:08+07:00
|
date: 2025-02-24T09:58:08+07:00
|
||||||
draft: false
|
draft: false
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -10,6 +10,7 @@ tags:
|
||||||
---
|
---
|
||||||
|
|
||||||
# Background
|
# Background
|
||||||
|
|
||||||
When searching techniques for syncing data between peers, I stumbled upon CRDT (Conflict-free Replicated Data Types). It's basically a algorithm for syncing for distributed systems. CRDT ensures all data changes between peer will be synced with correct order and no data loss.
|
When searching techniques for syncing data between peers, I stumbled upon CRDT (Conflict-free Replicated Data Types). It's basically a algorithm for syncing for distributed systems. CRDT ensures all data changes between peer will be synced with correct order and no data loss.
|
||||||
|
|
||||||
Since I working with Dart (for Flutter project), I use a [CRDT library for Dart](https://github.com/cachapa/crdt). This library implements core concept of CRDT and it's pretty basic. Here some types of CRDT that often used:
|
Since I working with Dart (for Flutter project), I use a [CRDT library for Dart](https://github.com/cachapa/crdt). This library implements core concept of CRDT and it's pretty basic. Here some types of CRDT that often used:
|
||||||
|
|
@ -21,63 +22,75 @@ Since I working with Dart (for Flutter project), I use a [CRDT library for Dart]
|
||||||
5. **OR-Set (Observed Remove Set)**: A set that allows elements to be added and removed, using unique identifiers to track additions and removals.
|
5. **OR-Set (Observed Remove Set)**: A set that allows elements to be added and removed, using unique identifiers to track additions and removals.
|
||||||
6. **LWW-Register (Last Write Wins Register)**: A register that stores the last written value, using a timestamp to determine the most recent update.
|
6. **LWW-Register (Last Write Wins Register)**: A register that stores the last written value, using a timestamp to determine the most recent update.
|
||||||
7. **MV-Register (Multi-Value Register)**: A register that stores all values that have been written, using unique identifiers to track writes.
|
7. **MV-Register (Multi-Value Register)**: A register that stores all values that have been written, using unique identifiers to track writes.
|
||||||
|
|
||||||
# How it works -- basic version
|
# How it works -- basic version
|
||||||
|
|
||||||
Main components:
|
Main components:
|
||||||
|
|
||||||
- HLC (Hardware Logical Clock). Combines _wall clock/local time_, a counter that increments, and an optional _node ID_ for uniqueness sake.
|
- HLC (Hardware Logical Clock). Combines _wall clock/local time_, a counter that increments, and an optional _node ID_ for uniqueness sake.
|
||||||
- The data itself (usually contains a key, value, and the HLC object).
|
- The data itself (usually contains a key, value, and the HLC object).
|
||||||
|
|
||||||
## **Scenario: Two Devices Synchronizing Data**
|
## **Scenario: Two Devices Synchronizing Data**
|
||||||
|
|
||||||
We have two devices, **Device A** and **Device B**, which both maintain their own local datasets. Each device can modify data independently. When they synchronize, their CRDT implementations will merge their changes and resolve conflicts.
|
We have two devices, **Device A** and **Device B**, which both maintain their own local datasets. Each device can modify data independently. When they synchronize, their CRDT implementations will merge their changes and resolve conflicts.
|
||||||
|
|
||||||
## Initial State
|
## Initial State
|
||||||
|
|
||||||
- Both devices start with the same data:
|
- Both devices start with the same data:
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----- | --------- | ------------- |
|
||||||
| 1 | Alice | false | HLC: A1 |
|
| 1 | Alice | false | HLC: A1 |
|
||||||
| 2 | Bob | false | HLC: A2 |
|
| 2 | Bob | false | HLC: A2 |
|
||||||
|
|
||||||
- Device A's last modified HLC: `A2`.
|
- Device A's last modified HLC: `A2`.
|
||||||
- Device B's last modified HLC: `A2`.
|
- Device B's last modified HLC: `A2`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Changes Made on Each Device
|
## Changes Made on Each Device
|
||||||
|
|
||||||
1. **Device A deletes Bob's record (key 2):**
|
1. **Device A deletes Bob's record (key 2):**
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----- | --------- | ------------- |
|
||||||
| 2 | null | true | HLC: A3 |
|
| 2 | null | true | HLC: A3 |
|
||||||
|
|
||||||
2. **Device B updates Alice's name to Alice Smith (key 1):**
|
2. **Device B updates Alice's name to Alice Smith (key 1):**
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----------- | --------- | ------------- |
|
||||||
| 1 | Alice Smith | false | HLC: B3 |
|
| 1 | Alice Smith | false | HLC: B3 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Synchronization and Merge
|
## Synchronization and Merge
|
||||||
|
|
||||||
- Device A sends its **changeset** to Device B:
|
- Device A sends its **changeset** to Device B:
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----- | --------- | ------------- |
|
||||||
| 2 | null | true | HLC: A3 |
|
| 2 | null | true | HLC: A3 |
|
||||||
|
|
||||||
- Device B sends its **changeset** to Device A:
|
- Device B sends its **changeset** to Device A:
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----------- | --------- | ------------- |
|
||||||
| 1 | Alice Smith | false | HLC: B3 |
|
| 1 | Alice Smith | false | HLC: B3 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Step-by-Step Conflict Resolution
|
## Step-by-Step Conflict Resolution
|
||||||
|
|
||||||
The `merge` method processes these changes:
|
The `merge` method processes these changes:
|
||||||
|
|
||||||
1. **Validate Changeset**:
|
1. **Validate Changeset**:
|
||||||
Each incoming record is validated to ensure it matches the expected schema and contains valid HLC timestamps.
|
Each incoming record is validated to ensure it matches the expected schema and contains valid HLC timestamps.
|
||||||
|
|
||||||
2. **Compare Records for Key 1 (`Alice`)**:
|
2. **Compare Records for Key 1 (`Alice`)**:
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----- | --------- | ------------- |
|
||||||
| 1 | Alice | false | HLC: A1 |
|
| 1 | Alice | false | HLC: A1 |
|
||||||
|
|
||||||
Incoming record from Device B:
|
Incoming record from Device B:
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
|
|
@ -86,15 +99,15 @@ Incoming record from Device B:
|
||||||
|
|
||||||
**Conflict Resolution Rule**: The record with the higher `Last Modified` HLC wins. HLC `B3 > A1,` so Device A updates Alice's record to:
|
**Conflict Resolution Rule**: The record with the higher `Last Modified` HLC wins. HLC `B3 > A1,` so Device A updates Alice's record to:
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----------- | --------- | ------------- |
|
||||||
| 1 | Alice Smith | false | HLC: B3 |
|
| 1 | Alice Smith | false | HLC: B3 |
|
||||||
|
|
||||||
3. **Compare Records for Key 2 (`Bob`)**:
|
3. **Compare Records for Key 2 (`Bob`)**:
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----- | --------- | ------------- |
|
||||||
| 2 | Bob | false | HLC: A2 |
|
| 2 | Bob | false | HLC: A2 |
|
||||||
|
|
||||||
Incoming record from Device A:
|
Incoming record from Device A:
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
|
|
@ -105,20 +118,22 @@ Incoming record from Device A:
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----- | --------- | ------------- |
|
||||||
| 2 | null | true | HLC: A3 |
|
| 2 | null | true | HLC: A3 |
|
||||||
|
|
||||||
4. **Propagate Changes**:
|
4. **Propagate Changes**:
|
||||||
Both devices now have identical datasets after merging.
|
Both devices now have identical datasets after merging.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Final Merged Dataset on Both Devices
|
## Final Merged Dataset on Both Devices
|
||||||
|
|
||||||
| Key | Value | isDeleted | Last Modified |
|
| Key | Value | isDeleted | Last Modified |
|
||||||
| --- | ----- | --------- | ------------- |
|
| --- | ----------- | --------- | ------------- |
|
||||||
| 1 | Alice Smith | false | HLC: B3 |
|
| 1 | Alice Smith | false | HLC: B3 |
|
||||||
| 2 | null | true | HLC: A3 |
|
| 2 | null | true | HLC: A3 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Summary of Conflict Resolution Rules
|
## Summary of Conflict Resolution Rules
|
||||||
|
|
||||||
1. **Higher HLC Wins**
|
1. **Higher HLC Wins**
|
||||||
|
|
@ -127,4 +142,3 @@ Incoming record from Device A:
|
||||||
A `null` value with `isDeleted: true` is treated as a soft delete. It wins if its HLC is higher.
|
A `null` value with `isDeleted: true` is treated as a soft delete. It wins if its HLC is higher.
|
||||||
3. **Deterministic Behavior**
|
3. **Deterministic Behavior**
|
||||||
All nodes independently apply the same conflict resolution logic, ensuring eventual consistency.
|
All nodes independently apply the same conflict resolution logic, ensuring eventual consistency.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'Fix ADB Insufficient Permission'
|
title: "Fix ADB Insufficient Permission"
|
||||||
description: 'udev rules for fixing ADB Insufficient permission in Linux'
|
description: "udev rules for fixing ADB Insufficient permission in Linux"
|
||||||
date: 2025-02-24T11:29:30+07:00
|
date: 2025-02-24T11:29:30+07:00
|
||||||
draft: false
|
draft: false
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -10,6 +10,7 @@ tags:
|
||||||
---
|
---
|
||||||
|
|
||||||
# Why need this?
|
# Why need this?
|
||||||
|
|
||||||
Connecting an Android device to a Linux computer could has problem with permission. Listing devices with `adb devices` might show `unauthorized` status or `insufficient permission` error message.
|
Connecting an Android device to a Linux computer could has problem with permission. Listing devices with `adb devices` might show `unauthorized` status or `insufficient permission` error message.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -33,7 +34,7 @@ $ lsusb
|
||||||
Bus 001 Device 005: ID 18d1:4ee7 Google Inc. Nexus/Pixel Device
|
Bus 001 Device 005: ID 18d1:4ee7 Google Inc. Nexus/Pixel Device
|
||||||
```
|
```
|
||||||
|
|
||||||
`18d1` is *vendor id* and `4ee7` is the *product id*.
|
`18d1` is _vendor id_ and `4ee7` is the _product id_.
|
||||||
|
|
||||||
2. Create an `udev` rule for this device, I create mine in `/etc/udev/rules.d/51-android.rules`.
|
2. Create an `udev` rule for this device, I create mine in `/etc/udev/rules.d/51-android.rules`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'Fix Infinix Air Pro+ Quad Speakers in Linux'
|
title: "Fix Infinix Air Pro+ Quad Speakers in Linux"
|
||||||
description: 'A fix for Infinix Air Pro+ -- only 2 of 4 speakers working in Linux'
|
description: "A fix for Infinix Air Pro+ -- only 2 of 4 speakers working in Linux"
|
||||||
date: 2025-02-23T23:27:49+07:00
|
date: 2025-02-23T23:27:49+07:00
|
||||||
draft: false
|
draft: false
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -83,8 +83,8 @@ $ sudo pacman -S alsa-tools
|
||||||
$ sudo hdajackretask
|
$ sudo hdajackretask
|
||||||
```
|
```
|
||||||
|
|
||||||
After opening the tool, check the `Show unconnected pins` and there will be list of nodes that can be retasked.
|
After opening the tool, check the `Show unconnected pins` and there will be list of nodes that can be retasked.
|
||||||
I need to experiment with this remapping. After trials and errors, I found that `0x1a` and `0x1b` is the responsible nodes for my extra speakers. Overriding them and changing their role as `Internal Speaker` solve my issue.
|
I need to experiment with this remapping. After trials and errors, I found that `0x1a` and `0x1b` is the responsible nodes for my extra speakers. Overriding them and changing their role as `Internal Speaker` solve my issue.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'Fix Infinix Air Pro+ Screen Color'
|
title: "Fix Infinix Air Pro+ Screen Color"
|
||||||
description: 'Fixing Infinix Air Pro+ washed out screen color in Windows and Linux'
|
description: "Fixing Infinix Air Pro+ washed out screen color in Windows and Linux"
|
||||||
date: 2025-02-21T18:09:54+07:00
|
date: 2025-02-21T18:09:54+07:00
|
||||||
draft: false
|
draft: false
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -10,26 +10,29 @@ tags:
|
||||||
- script
|
- script
|
||||||
---
|
---
|
||||||
|
|
||||||
I have Infinix Air Pro+ and I use it for my work. I can say it is a good laptop coding mainly because it has 2.5k OLED 16:10 screen. But I found a problem with its screen color. When the screen brightness is below about 50% and the screen turned off (to save power, not necessarily going system sleep/suspend) and turns back on, the color looks washed out.
|
I have Infinix Air Pro+ and I use it for my work. I can say it is a good laptop coding mainly because it has 2.5k OLED 16:10 screen. But I found a problem with its screen color. When the screen brightness is below about 50% and the screen turned off (to save power, not necessarily going system sleep/suspend) and turns back on, the color looks washed out.
|
||||||
|
|
||||||
First time I noticed this issue is because I was using a pitch black wallpaper image (so I can flex my OLED display). After my screen turns back on, my wallpaper's black color becomes grainy, washed out, as its doesn't have pitch black color anymore. Then I noticed, the color will be fixed after I crank the brightness to above 50%. Turning the brightness down again after this still gives me correct black level.
|
First time I noticed this issue is because I was using a pitch black wallpaper image (so I can flex my OLED display). After my screen turns back on, my wallpaper's black color becomes grainy, washed out, as its doesn't have pitch black color anymore. Then I noticed, the color will be fixed after I crank the brightness to above 50%. Turning the brightness down again after this still gives me correct black level.
|
||||||
|
|
||||||
So, I was wondering if I create a script that will turn the brightness to above 50% and restore it to where it was every time my screen is waking up from a sleep. With a help from Google and ChatGPT, I create these scripts as a workaround for this annoying issue.
|
So, I was wondering if I create a script that will turn the brightness to above 50% and restore it to where it was every time my screen is waking up from a sleep. With a help from Google and ChatGPT, I create these scripts as a workaround for this annoying issue.
|
||||||
|
|
||||||
# Windows
|
# Windows
|
||||||
|
|
||||||
Before continuing, I'm sorry I can't give any screenshot for this Windows section because I already switched to Linux, but I hope I can write it clearly.
|
Before continuing, I'm sorry I can't give any screenshot for this Windows section because I already switched to Linux, but I hope I can write it clearly.
|
||||||
|
|
||||||
## Get screen wake up event
|
## Get screen wake up event
|
||||||
I need to listen to an event that tells me "Hey, the screen is turning on". Fortunately, Windows has [Event Viewer](https://learn.microsoft.com/en-us/shows/inside/event-viewer) that I can use for this. I found that an event from *Kernel-Power* with event ID *507* is the correct event that means the screen in turned back on.
|
|
||||||
|
I need to listen to an event that tells me "Hey, the screen is turning on". Fortunately, Windows has [Event Viewer](https://learn.microsoft.com/en-us/shows/inside/event-viewer) that I can use for this. I found that an event from _Kernel-Power_ with event ID _507_ is the correct event that means the screen in turned back on.
|
||||||
|
|
||||||
## Script
|
## Script
|
||||||
|
|
||||||
Next thing to do is create the script to control screen brightness. After trial and error, I found [NirCmd](https://www.nirsoft.net/utils/nircmd.html) can help me to change my screen brightness. Then I create this Powershell script.
|
Next thing to do is create the script to control screen brightness. After trial and error, I found [NirCmd](https://www.nirsoft.net/utils/nircmd.html) can help me to change my screen brightness. Then I create this Powershell script.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Infinix Air Pro Plus suffers from washed out colors
|
# Infinix Air Pro Plus suffers from washed out colors
|
||||||
# after the display goes off and back on if the brightness is below 50%.
|
# after the display goes off and back on if the brightness is below 50%.
|
||||||
# This script will increase the brightness to 60% when initial brightness
|
# This script will increase the brightness to 60% when initial brightness
|
||||||
# is below 50% else it will increase 10% from current brightness and turn
|
# is below 50% else it will increase 10% from current brightness and turn
|
||||||
# back to initial brightness value.
|
# back to initial brightness value.
|
||||||
|
|
||||||
# Path to NirCmd executable
|
# Path to NirCmd executable
|
||||||
|
|
@ -64,17 +67,21 @@ if ($currentBrightness -lt 50) {
|
||||||
```
|
```
|
||||||
|
|
||||||
## Make a schedule
|
## Make a schedule
|
||||||
I use Windows' [Task Scheduler](https://www.windowscentral.com/how-create-automated-tasks-windows-11) to run the script each time *Kernel-Power* with event ID *507* occurs. I can't show the step-by-step guide because I'm on Linux now, but I have a backup file for this task. All you need is just to import [this task](/misc/Restore%20OLED%20Colors.xml) in Task Scheduler.
|
|
||||||
|
I use Windows' [Task Scheduler](https://www.windowscentral.com/how-create-automated-tasks-windows-11) to run the script each time _Kernel-Power_ with event ID _507_ occurs. I can't show the step-by-step guide because I'm on Linux now, but I have a backup file for this task. All you need is just to import [this task](/misc/Restore%20OLED%20Colors.xml) in Task Scheduler.
|
||||||
|
|
||||||
> Note: You have to change the command it executes to where you save the Powershell script. Also change the author into `YOUR_PC_NAME\YOUR_USERNAME`.
|
> Note: You have to change the command it executes to where you save the Powershell script. Also change the author into `YOUR_PC_NAME\YOUR_USERNAME`.
|
||||||
|
|
||||||
# Linux
|
# Linux
|
||||||
|
|
||||||
I'm using [EndeavourOS](https://endeavouros.com/) which use `systemd`. So this guide is applicable to `systemd` init system only. If your linux use something else, you need to adjust it with your init system.
|
I'm using [EndeavourOS](https://endeavouros.com/) which use `systemd`. So this guide is applicable to `systemd` init system only. If your linux use something else, you need to adjust it with your init system.
|
||||||
|
|
||||||
## Get screen wake up event
|
## Get screen wake up event
|
||||||
|
|
||||||
I already tried several ways to listen the screen wake up events. But I can't find any using `acpi` and `udev`. So I tried different approach. I check `dpms` property from screen device in `/sys/class/drm/card1-eDP-1/dpms`. It has `On` and `Off` value that I can use for triggering a script to fix the color.
|
I already tried several ways to listen the screen wake up events. But I can't find any using `acpi` and `udev`. So I tried different approach. I check `dpms` property from screen device in `/sys/class/drm/card1-eDP-1/dpms`. It has `On` and `Off` value that I can use for triggering a script to fix the color.
|
||||||
|
|
||||||
## Script
|
## Script
|
||||||
|
|
||||||
I have 2 scripts for this approach. One for checking `/sys/class/drm/card1-eDP-1/dpms` value and another one for fixing the color.
|
I have 2 scripts for this approach. One for checking `/sys/class/drm/card1-eDP-1/dpms` value and another one for fixing the color.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -86,7 +93,7 @@ prev_state=""
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
state=$(cat /sys/class/drm/card1-eDP-1/dpms)
|
state=$(cat /sys/class/drm/card1-eDP-1/dpms)
|
||||||
|
|
||||||
if [[ "$state" != "$prev_state" && "$state" == "On" ]]; then
|
if [[ "$state" != "$prev_state" && "$state" == "On" ]]; then
|
||||||
echo "Screen turned on! Running script..."
|
echo "Screen turned on! Running script..."
|
||||||
/usr/local/bin/brightness_fix.sh
|
/usr/local/bin/brightness_fix.sh
|
||||||
|
|
@ -137,6 +144,7 @@ fi
|
||||||
```
|
```
|
||||||
|
|
||||||
## Make a systemd service
|
## Make a systemd service
|
||||||
|
|
||||||
Make a `systemd` service in `/etc/systemd/system/brightness-fix.service` to run the first script.
|
Make a `systemd` service in `/etc/systemd/system/brightness-fix.service` to run the first script.
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
|
|
@ -171,10 +179,10 @@ WantedBy=suspend.target
|
||||||
Then register, enable, and start it.
|
Then register, enable, and start it.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl enable brightness-fix.service
|
sudo systemctl enable brightness-fix.service
|
||||||
sudo systemctl enable brightness-fix-wakeup.service
|
sudo systemctl enable brightness-fix-wakeup.service
|
||||||
sudo systemctl start brightness-fix.service
|
sudo systemctl start brightness-fix.service
|
||||||
```
|
```
|
||||||
|
|
||||||
One more thing, you can add also `/usr/local/bin/brightness_fix.sh` to autostart (I'm using KDE) so it will run each time you login.
|
One more thing, you can add also `/usr/local/bin/brightness_fix.sh` to autostart (I'm using KDE) so it will run each time you login.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: 'Android Devices Not Showing on Flutter Project'
|
title: "Android Devices Not Showing on Flutter Project"
|
||||||
description: "A fix for new Flutter project that doesn't have Android devices showing up"
|
description: "A fix for new Flutter project that doesn't have Android devices showing up"
|
||||||
date: 2025-02-22T09:21:22+07:00
|
date: 2025-02-22T09:21:22+07:00
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -22,4 +22,4 @@ As you can see, I have no Android SDK selected for my Flutter project. So, go ah
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Hope this can help someone who has similar issues with Flutter project and Android devices.
|
Hope this can help someone who has similar issues with Flutter project and Android devices.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'Kuwot'
|
title: "Kuwot"
|
||||||
description: 'Flutter Daily Quote App'
|
description: "Flutter Daily Quote App"
|
||||||
date: 2025-02-20T15:26:04+07:00
|
date: 2025-02-20T15:26:04+07:00
|
||||||
draft: true
|
draft: true
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -11,9 +11,11 @@ tags:
|
||||||
I made [Kuwot](https://play.google.com/store/apps/details?id=com.dhemasnurjaya.kuwot) last year in my spare time. I want to share it, you can use it as an inspiration, practice app, or something else is up to you since I open-sourced the code (links below).
|
I made [Kuwot](https://play.google.com/store/apps/details?id=com.dhemasnurjaya.kuwot) last year in my spare time. I want to share it, you can use it as an inspiration, practice app, or something else is up to you since I open-sourced the code (links below).
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
The Flutter app itself was built using [Clean Architecture]({{< ref "/posts/flutter-clean-architecture/index.md" >}}). It has all basic features from a daily quote application. At first, my idea is to make a simple daily quote application. Showing random quote everytime the app is opened, and give it an image background to make it more appealing.
|
The Flutter app itself was built using [Clean Architecture]({{< ref "/posts/flutter-clean-architecture/index.md" >}}). It has all basic features from a daily quote application. At first, my idea is to make a simple daily quote application. Showing random quote everytime the app is opened, and give it an image background to make it more appealing.
|
||||||
|
|
||||||
# Hunting for quote data
|
# Hunting for quote data
|
||||||
|
|
||||||
First thing I did was searching some kind of quote data that available for free. I stumbled across several choices:
|
First thing I did was searching some kind of quote data that available for free. I stumbled across several choices:
|
||||||
|
|
||||||
- Use available quote API, eg: [Zen Quotes](https://zenquotes.io)
|
- Use available quote API, eg: [Zen Quotes](https://zenquotes.io)
|
||||||
|
|
@ -25,15 +27,17 @@ After many consideration, I'd like to use this [Quotes 500k](https://github.com/
|
||||||
First problem solved, since I have the quote dataset I was thinking whether I embed this dataset as SQLite database into the app or do something else. But then I remember that I still need to get the background image for the app and it will make no sense to embed the background images into the app as well. So I decided to create a simple REST API for Kuwot.
|
First problem solved, since I have the quote dataset I was thinking whether I embed this dataset as SQLite database into the app or do something else. But then I remember that I still need to get the background image for the app and it will make no sense to embed the background images into the app as well. So I decided to create a simple REST API for Kuwot.
|
||||||
|
|
||||||
# Building the API
|
# Building the API
|
||||||
|
|
||||||
Now I need a simple, easy to make REST API. I was thinking to use Python's [FastAPI](https://fastapi.tiangolo.com/) but after some onboarding tutorial, I just don't like it. Then I found [dart_frog](https://dartfrog.vgv.dev/)! It's a minimalist backend framework written in Dart. There are no reason to not use this since it use same language as my Flutter app, that was I thought.
|
Now I need a simple, easy to make REST API. I was thinking to use Python's [FastAPI](https://fastapi.tiangolo.com/) but after some onboarding tutorial, I just don't like it. Then I found [dart_frog](https://dartfrog.vgv.dev/)! It's a minimalist backend framework written in Dart. There are no reason to not use this since it use same language as my Flutter app, that was I thought.
|
||||||
|
|
||||||
Building the API is straight-forward, [dart_frog](https://dartfrog.vgv.dev/) has everything I need to build the API.
|
Building the API is straight-forward, [dart_frog](https://dartfrog.vgv.dev/) has everything I need to build the API.
|
||||||
|
|
||||||
# Reshaping dataset
|
# Reshaping dataset
|
||||||
|
|
||||||
The data I got from [Quotes 500k](https://github.com/ShivaliGoel/Quotes-500K) is looking like this:
|
The data I got from [Quotes 500k](https://github.com/ShivaliGoel/Quotes-500K) is looking like this:
|
||||||
|
|
||||||
| Quote | Author | Tags |
|
| Quote | Author | Tags |
|
||||||
| ----- | ------ | ---- |
|
| ---------------------------------------------------------------- | -------------- | ----------------------------------- |
|
||||||
| A friend is someone who knows all about you and still loves you. | Elbert Hubbard | friend, friendship, knowledge, love |
|
| A friend is someone who knows all about you and still loves you. | Elbert Hubbard | friend, friendship, knowledge, love |
|
||||||
|
|
||||||
Now, I didn't want the tags and I don't want a long quote. So I make a Python script to filter those quotes into a new dataset I need.
|
Now, I didn't want the tags and I don't want a long quote. So I make a Python script to filter those quotes into a new dataset I need.
|
||||||
|
|
@ -43,4 +47,5 @@ Now, I didn't want the tags and I don't want a long quote. So I make a Python sc
|
||||||
```
|
```
|
||||||
|
|
||||||
# UI Design
|
# UI Design
|
||||||
I want to make it as simple as possible while focusing on the functionality.
|
|
||||||
|
I want to make it as simple as possible while focusing on the functionality.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'Remap Infinix Air Pro+ Copilot Key in Linux'
|
title: "Remap Infinix Air Pro+ Copilot Key in Linux"
|
||||||
description: 'Re-using Copilot key for something else more useful'
|
description: "Re-using Copilot key for something else more useful"
|
||||||
date: 2025-03-01T22:41:32+07:00
|
date: 2025-03-01T22:41:32+07:00
|
||||||
draft: false
|
draft: false
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -10,15 +10,17 @@ tags:
|
||||||
- tweak
|
- tweak
|
||||||
---
|
---
|
||||||
|
|
||||||
> Since I'm moving to Linux, my Copilot key becomes useless.
|
> Since I'm moving to Linux, my Copilot key becomes useless.
|
||||||
|
|
||||||
Let me rephrase that! Even when I was using Windows, I never using this Copilot shortcut key in my keyboard 😬. Fortunately, using Linux I can remap this key for something else ~~more useful~~.
|
Let me rephrase that! Even when I was using Windows, I never using this Copilot shortcut key in my keyboard 😬. Fortunately, using Linux I can remap this key for something else ~~more useful~~.
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
- A laptop (I'm using Infinix Air Pro+) with a working keyboard.
|
- A laptop (I'm using Infinix Air Pro+) with a working keyboard.
|
||||||
- [keyd](https://github.com/rvaiya/keyd)
|
- [keyd](https://github.com/rvaiya/keyd)
|
||||||
|
|
||||||
# Finding what this Copilot key do
|
# Finding what this Copilot key do
|
||||||
|
|
||||||
- Open your favorite terminal and execute `sudo keyd monitor`. This command will print what events are triggered when a particular key is pressed.
|
- Open your favorite terminal and execute `sudo keyd monitor`. This command will print what events are triggered when a particular key is pressed.
|
||||||
- Press the Copilot key and read the output. In my laptop, it print out this:
|
- Press the Copilot key and read the output. In my laptop, it print out this:
|
||||||
|
|
||||||
|
|
@ -31,13 +33,14 @@ AT Translated Set 2 keyboard 0001:0001:70533846 f23 down
|
||||||
- Now I know that my copilot key triggers `leftmeta`, `leftshift`, and `f23`. It's seem legit combination of modifier keys and a function key. But unfortunately when I tried to use it in my desktop environment (I use KDE) to bind a shortcut, it only detect the modifier `meta` and `shift`.
|
- Now I know that my copilot key triggers `leftmeta`, `leftshift`, and `f23`. It's seem legit combination of modifier keys and a function key. But unfortunately when I tried to use it in my desktop environment (I use KDE) to bind a shortcut, it only detect the modifier `meta` and `shift`.
|
||||||
|
|
||||||
# `keyd` for the rescue
|
# `keyd` for the rescue
|
||||||
|
|
||||||
Edit `/etc/keyd/default.conf` file and I added these lines:
|
Edit `/etc/keyd/default.conf` file and I added these lines:
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
[ids]
|
[ids]
|
||||||
0001:0001:70533846
|
0001:0001:70533846
|
||||||
|
|
||||||
[main]
|
[main]
|
||||||
f23 = f13
|
f23 = f13
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'Welcome'
|
title: "Welcome"
|
||||||
description: 'Initial commit!'
|
description: "Initial commit!"
|
||||||
date: 2024-03-18T14:16:19+07:00
|
date: 2024-03-18T14:16:19+07:00
|
||||||
draft: false
|
draft: false
|
||||||
tags:
|
tags:
|
||||||
|
|
@ -15,9 +15,8 @@ Long story short, I decide to take an Information Technology major in my local u
|
||||||
|
|
||||||
I never really write anything in my 7 years journey and I feel kinda regretted it. So I decide to create this blog, where I can write anything I found interesting. Maybe it's a coding-related thing, technology heads up, or maybe just my random thought. Feel free read and share!
|
I never really write anything in my 7 years journey and I feel kinda regretted it. So I decide to create this blog, where I can write anything I found interesting. Maybe it's a coding-related thing, technology heads up, or maybe just my random thought. Feel free read and share!
|
||||||
|
|
||||||
|
|
||||||
# Bonus
|
# Bonus
|
||||||
|
|
||||||
This is a cat from my work, maybe someday she can be a good software tester to find ~~mice~~ bugs from my code.
|
This is a cat from my work, maybe someday she can be a good software tester to find ~~mice~~ bugs from my code.
|
||||||
|
|
||||||
  
|
  
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import "../styles/global.css";
|
import "@/styles/global.css";
|
||||||
import Footer from "../components/Footer.astro";
|
import Footer from "@/components/Footer.astro";
|
||||||
import Header from "../components/Header.astro";
|
import Header from "@/components/Header.astro";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import Welcome from "../components/Welcome.astro";
|
import Welcome from "@/components/Welcome.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
|
||||||
// Welcome to Astro! Wondering what to do next? Check out the Astro documentation at https://docs.astro.build
|
// Welcome to Astro! Wondering what to do next? Check out the Astro documentation at https://docs.astro.build
|
||||||
// Don't want to use any of this? Delete everything in this file, the `assets`, `components`, and `layouts` directories, and start fresh.
|
// Don't want to use any of this? Delete everything in this file, the `assets`, `components`, and `layouts` directories, and start fresh.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import { getCollection, render, type CollectionEntry, type RenderResult } from "astro:content";
|
import { getCollection, render, type CollectionEntry, type RenderResult } from "astro:content";
|
||||||
import Layout from "../../layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
import BlogPost from "../../components/BlogPost.astro";
|
import BlogPost from "@/components/BlogPost.astro";
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await getCollection("blog");
|
const posts = await getCollection("blog");
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import Layout from "../../layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
import BlogPostCard from "../../components/BlogPostCard.astro";
|
import BlogPostCard from "@/components/BlogPostCard.astro";
|
||||||
|
|
||||||
const posts = await getCollection("blog");
|
const posts = await getCollection("blog");
|
||||||
posts.sort((a, b) => b.data.date.getTime() - a.data.date.getTime());
|
posts.sort((a, b) => b.data.date.getTime() - a.data.date.getTime());
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import { getCollection, type CollectionEntry } from "astro:content";
|
import { getCollection, type CollectionEntry } from "astro:content";
|
||||||
import BlogPostCard from "../../components/BlogPostCard.astro";
|
import BlogPostCard from "@/components/BlogPostCard.astro";
|
||||||
import Layout from "../../layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await getCollection("blog");
|
const posts = await getCollection("blog");
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import Layout from "../../layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
|
||||||
const posts = await getCollection("blog");
|
const posts = await getCollection("blog");
|
||||||
const tagsMap = new Map<string, number>();
|
const tagsMap = new Map<string, number>();
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap');
|
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap");
|
||||||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
|
@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap");
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@plugin '@tailwindcss/typography';
|
@plugin '@tailwindcss/typography';
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--font-sans: 'Noto Sans', sans-serif;
|
--font-sans: "Noto Sans", sans-serif;
|
||||||
--font-mono: 'JetBrains Mono', monospace;
|
--font-mono: "JetBrains Mono", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
body {
|
body {
|
||||||
@apply bg-zinc-900 text-zinc-300;
|
@apply bg-zinc-900 text-zinc-300;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,10 @@
|
||||||
"include": [".astro/types.d.ts", "**/*"],
|
"include": [".astro/types.d.ts", "**/*"],
|
||||||
"exclude": ["dist"],
|
"exclude": ["dist"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowJs": true
|
"allowJs": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue