How to show anchor bottom view in SwiftUI

Issue #954 From iOS 15, there鈥檚 a handy safeAreaInset that allows us to place additional content extending the safe area. Shows the specified content beside the modified view. safeAreaInset allows us to customize which edge and alignment we can place our views. This works for both ScrollView, List and Form and you can apply it multiple times. The content view is anchored to the specified horizontal edge in the parent view, aligning its vertical axis to the specified alignment guide....

November 22, 2023 路 2 min 路 Khoa Pham

How to debounce text input in React

Issue #953 Use debounce from lodash and useCallback to memoize debounce function import React, { useCallback } from "react" import debounce from "lodash/debounce" const SearchField = (props: Props) => { const callback = useCallback( debounce((value: string) => { props.setFilter({ ...props.filter, searchText: value, }) }), [] ) const handleChange = (value: string) => { callback(value) } return ( <div> <Input value={props.filter.searchText} placeholder="Search" variant="bordered" onValueChange={handleChange} /> </div> ) }

November 19, 2023 路 1 min 路 Khoa Pham

How to remove duplicates in Javascript array while keeping latest occurrence?

Issue #952 Use ES6 Map The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value. type Deal = { name: string, link: string } removeDuplicates = (array: Deal[]) => { const map = new Map() array.forEach((item) => map.set(, item)) return [] } We might need to update tsconfig....

November 17, 2023 路 1 min 路 Khoa Pham

How to drag multiple files in SwiftUI on Mac

Issue #951 Create a custom NSView that handles mouseDragged to beginDraggingSession struct DraggingSourceViewWrapper: NSViewRepresentable { let fileUrls: [URL] let onEnd: () -> Void func makeNSView(context: Context) -> DraggingSourceView { let view = DraggingSourceView(fileUrls: fileUrls) view.onEnd = onEnd return view } func updateNSView(_ view: DraggingSourceView, context: Context) { view.onEnd = onEnd } } final class DraggingSourceView: NSView { let fileUrls: [URL] var onEnd: (() -> Void)? init(fileUrls: [URL]) { self.fileUrls = fileUrls super....

November 13, 2023 路 2 min 路 Khoa Pham

How to dynamically build tailwind class names

Issue #950 Inspired by shadcn Combine tailwind-merge: Utility function to efficiently merge Tailwind CSS classes in JS without style conflicts. clsx: constructing className strings conditionally. import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) }

November 4, 2023 路 1 min 路 Khoa Pham

How to store Codable in AppStorage

Issue #949 AppStorage and SceneStorage accepts RawRepresentable where value is Int or String. Creates a property that can read and write to a string user default, transforming that to RawRepresentable data type. init(wrappedValue:_:store:) init( wrappedValue: Value, _ key: String, store: UserDefaults? = nil ) where Value : RawRepresentable, Value.RawValue == String One clever thing (that does not work) is to use a custom Codable type that conforms to RawRepresentable, like below...

October 3, 2023 路 2 min 路 Khoa Pham

How to update widget for iOS 17

Issue #948 iOS 17 has a new Stand by mode so SwiftUI introduces containerBackground for the system to decide when to draw background. It also automatically applies margin to widget so we may need to disable that To update existing widgets, we can write some useful extension extension View { @ViewBuilder func safeContainerBackground(@ViewBuilder content: () -> some View) -> some View { if #available(iOS 17.0, *) { self.containerBackground(for: .widget, content: content) } else { self....

October 2, 2023 路 1 min 路 Khoa Pham

How to get Supabase user token from server API

Issue #947 Sometimes Row Level Security is not enough and we want to do all logic server side, then we need a way for the server to get hold onto current user token. Send JWT token in Authorization header From client, we can get session from supabase auth, then send that as Bearer in Authorization header const session = await supabase.auth.getSession().data.session const token = session.access_token const response = await fetch(url, { 'GET', headers: { Authorization: `Bearer ${token}` } }) Decode token From the nextjs API Route, we can handle all auth logic in middleware....

August 30, 2023 路 2 min 路 Khoa Pham

How to mirror auth.users on Supabase

Issue #946 For security purposes, the auth schema is not exposed on the auto-generated API. We can make a profiles table in public namespace and mirror data from auth.users when user signs up. I need id, username and raw_user_metadata so I will mirror these columns. For easy, you can leverage Supabase SQL Editor -> Quickstarts -> User Management Starter script I don鈥檛 need Row Level Security as I manage database from server....

August 30, 2023 路 2 min 路 Khoa Pham

How to force localized language with SwiftGen

Issue #945 The default SwiftGen generate generated strings L10n file like this extension L10n { private static func tr(_ table: String, _ key: String, _ args: CVarArg..., fallback value: String) -> String { let format = BundleToken.bundle.localizedString(forKey: key, value: value, table: table) return String(format: format, locale: Locale.current, arguments: args) } } // swiftlint:disable convenience_type private final class BundleToken { static let bundle: Bundle = { #if SWIFT_PACKAGE return Bundle.module #else return Bundle(for: BundleToken....

August 26, 2023 路 1 min 路 Khoa Pham

How to make tag flow layout using Layout protocol in SwiftUI

Issue #944 SwiftUI in iOS 16 supports Layout protocol to arrange subviews We need to implement 2 methods sizeThatFits(proposal:subviews:cache:) reports the size of the composite layout view. placeSubviews(in:proposal:subviews:cache:) assigns positions to the container鈥檚 subviews. We will make a custom layout that arranges elements from top leading and span element to new rows if it can鈥檛 fit the current row. Start by defining a FlowLayout struct that conforms to Layout protocol....

August 22, 2023 路 3 min 路 Khoa Pham

How to use hover annotation in Swift Charts

Issue #943 In this tutorial, we鈥檒l learn how to use Swift Charts to visualize ranking data. We use default AxisMarks and AxisMarks to let Swift Charts interpolate x and y grid lines. For y axis, I want to have finer grain control over the grid, so I specify an arrayLiteral Note that for rank, the lower value the better ranking, so we make use of chartYScale with reversed automatic domain to flip from 0 -> 100 to 100 -> 0...

August 18, 2023 路 2 min 路 Khoa Pham

How to use Supabase auth with React Context

Issue #942 Expose supabase with createClient useSupabase.ts import { createClient } from '@supabase/supabase-js' const supabaseUrl = process.env.SUPABASE_URL const supabaseAnonKey = process.env.SUPABASE_ANON_KEY export const supabase = createClient(supabaseUrl!, supabaseAnonKey!) export const signIn = async () => { await supabase.auth.signInWithOAuth({ provider: 'twitter' }); } export const signOut = async () => { await supabase.auth.signOut(); } Wrap auth state in React Context AuthProvider.tsx import React, { useContext, createContext, useState, useEffect } from 'react' import { Session, User } from '@supabase/supabase-js' import { supabase } from '....

August 12, 2023 路 2 min 路 Khoa Pham

How to create React app with Parcel

Issue #941 In this tutorial we will be creating a React app with Parcel 2 with Typescript and Tailwind Install the following dependencies. Parcel supports TypeScript out of the box without any additional configuration. npm install --save-dev parcel npm install react react-dom npm install @types/react @types/react-dom --dev npm install -D tailwindcss postcss npx tailwindcss init We will be adding files to src folder src - index.html - App.tsx - App.css Create a ....

August 3, 2023 路 3 min 路 Khoa Pham

How to make Chrome extension with Nextjs 13

Issue #940 We can develop Nextjs 13 apps and export it to a Chrome extension. Start by init the project npx create-next-app@latest Here is the project structure with app router and not using src directory. I put an extension to the root of the project, where we can copy over the generated out folder extension - manifest.json app - page.tsx public - images Here is my script to build and copy over generated out and public images to extension folder...

August 2, 2023 路 1 min 路 Khoa Pham

How to scale image fill without affect layout in SwiftUI

Issue #939 Instead of letting the Image decide the size, we can put it as background or overlay. I use clipped and contentShape to avoid the fill image obscuring touch event Color.clear .frame(height: 100) .overlay { AsyncImage(url: item.imageUrl) { image in image .resizable() .scaledToFill() } placeholder: { ProgressView() } } .clipped() .contentShape(Rectangle())

July 30, 2023 路 1 min 路 Khoa Pham

How to move Core Data database to AppGroup folder

Issue #938 To let app and extension to talk to the same database, we need to use AppGroup. Here is how to use replacePersistentStore Replaces one persistent store with another actor DatabaseMigrator { @AppStorage("DatabaseMigrator.hasMigrated") var hasMigrated = false func migrateIfNeeded() { guard !hasMigrated else { return } migrate() hasMigrated = true } private func migrate() { let oldContainer = NSPersistentCloudKitContainer(name: "Bookmarks") guard let oldStoreUrl = oldContainer.persistentStoreDescriptions.first?.url, let newStoreUrl = Constants....

July 30, 2023 路 1 min 路 Khoa Pham

How to read write files to iCloud Drive

Issue #937 First, you need to enable iCloud Documents capability. Go to target settings -> Signing & Capabilities -> iCloud ` Then inside your Info.plist, add this with your iCloud identifier and app name <key>NSUbiquitousContainers</key> <dict> <key></key> <dict> <key>NSUbiquitousContainerIsDocumentScopePublic</key> <true/> <key>NSUbiquitousContainerName</key> <string>PastePal</string> <key>NSUbiquitousContainerSupportedFolderLevels</key> <string>Any</string> </dict> </dict> To access to your iCloud Drive folder, we use FileManager to retrieve the folder. Returns the URL for the iCloud container associated with the specified identifier and establishes access to that container....

July 28, 2023 路 2 min 路 Khoa Pham

How to make reusable Button component in React

Issue #936 From import { forwardRef } from "react"; import { twMerge } from "tailwind-merge"; export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {} const Button = forwardRef<HTMLButtonElement, ButtonProps>(({ className, children, disabled, type = 'button', ...props }, ref) => { return ( <button type={type} className={twMerge( ` w-full rounded-full bg-green-500 border border-transparent px-3 py-3 disabled:cursor-not-allowed disabled:opacity-50 text-black font-bold hover:opacity-75 transition `, disabled && 'opacity-75 cursor-not-allowed', className )} disabled={disabled} ref={ref} {...props} > {children} </button> ); }); Button....

July 21, 2023 路 1 min 路 Khoa Pham

How to make fullstack web app

Issue #935 I prefer UI Component that works with Nextjs and Tailwind CSS UI Libraries 馃憤 Tailwind CSS templates Icon Library Lib Services Support Ref

July 20, 2023 路 1 min 路 Khoa Pham