mirror of
https://github.com/VibedByKaKi/t3-code-android-nightly.git
synced 2026-10-09 11:51:15 +02:00
Some checks are pending
CI / Lint (push) Waiting to run
CI / Typecheck (push) Waiting to run
CI / Build (push) Waiting to run
CI / Test (push) Waiting to run
CI / Test Web (push) Waiting to run
CI / Test Server 1 (push) Waiting to run
CI / Test Server 2 (push) Waiting to run
CI / Test Server 3 (push) Waiting to run
CI / Test Server 4 (push) Waiting to run
CI / Test Server 5 (push) Waiting to run
CI / Test Server 6 (push) Waiting to run
CI / Transfer report artifact (push) Blocked by required conditions
CI / Rust (push) Waiting to run
CI / Mobile Native Changes (push) Waiting to run
CI / Mobile Native Static Analysis (push) Blocked by required conditions
CI / Release Smoke (push) Waiting to run
CI / Check (push) Blocked by required conditions
Forward to Cursor hygiene / POST to Cursor (push) Waiting to run
Deploy T3 Connect relay / Deploy production relay (push) Waiting to run
Mobile EAS Production / EAS production (push) Waiting to run
Co-authored-by: Yash Singh <saiansh2525@gmail.com> Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
interface ThreadSearchTextPart {
|
||
readonly text: string;
|
||
readonly highlighted: boolean;
|
||
readonly start: number;
|
||
}
|
||
|
||
function foldThreadSearchCase(text: string): string {
|
||
const lowered = text.toLowerCase().replace(/ς/g, "σ");
|
||
if (lowered.length === text.length) return lowered;
|
||
|
||
let folded = "";
|
||
for (const character of text) {
|
||
const loweredCharacter = character.toLowerCase().replace(/ς/g, "σ");
|
||
folded += loweredCharacter.length === character.length ? loweredCharacter : character;
|
||
}
|
||
return folded;
|
||
}
|
||
|
||
function scanThreadSearchOccurrences(text: string, query: string, offsets?: number[]): number {
|
||
if (text.length === 0 || query.length === 0) return 0;
|
||
|
||
const foldedText = foldThreadSearchCase(text);
|
||
const foldedQuery = foldThreadSearchCase(query);
|
||
let count = 0;
|
||
let cursor = 0;
|
||
|
||
while (cursor <= foldedText.length - foldedQuery.length) {
|
||
const offset = foldedText.indexOf(foldedQuery, cursor);
|
||
if (offset === -1) break;
|
||
offsets?.push(offset);
|
||
count += 1;
|
||
cursor = offset + foldedQuery.length;
|
||
}
|
||
return count;
|
||
}
|
||
|
||
export function countThreadSearchOccurrences(text: string, query: string): number {
|
||
return scanThreadSearchOccurrences(text, query);
|
||
}
|
||
|
||
export function findThreadSearchOccurrences(text: string, query: string): number[] {
|
||
const offsets: number[] = [];
|
||
scanThreadSearchOccurrences(text, query, offsets);
|
||
return offsets;
|
||
}
|
||
|
||
export function splitThreadSearchText(text: string, query: string): ThreadSearchTextPart[] {
|
||
const normalizedQuery = query.trim();
|
||
if (normalizedQuery.length === 0) {
|
||
return [{ text, highlighted: false, start: 0 }];
|
||
}
|
||
|
||
const parts: ThreadSearchTextPart[] = [];
|
||
let cursor = 0;
|
||
for (const offset of findThreadSearchOccurrences(text, normalizedQuery)) {
|
||
if (offset > cursor) {
|
||
parts.push({ text: text.slice(cursor, offset), highlighted: false, start: cursor });
|
||
}
|
||
parts.push({
|
||
text: text.slice(offset, offset + normalizedQuery.length),
|
||
highlighted: true,
|
||
start: offset,
|
||
});
|
||
cursor = offset + normalizedQuery.length;
|
||
}
|
||
if (cursor < text.length) {
|
||
parts.push({ text: text.slice(cursor), highlighted: false, start: cursor });
|
||
}
|
||
return parts;
|
||
}
|