Skip to content

Conversation

@muness
Copy link
Member

@muness muness commented Sep 26, 2025

Adds configurable field extraction patterns allowing users to extract any type of data from calendar events into custom fields, while maintaining backward compatibility with existing video call URL extraction.

What Changed

  • Generic Field Extraction: Expanded beyond video calls to extract any field type (phone numbers, meeting IDs, links, etc.)
  • Field Section Organization: Patterns are organized into field sections (e.g., "Video Call URLs", "Phone Numbers")
  • Flexible Pattern Matching: Support for "contains" and "regex" pattern types
  • Priority-Based Processing: Patterns are processed in order of priority (lower numbers first)
  • Automatic Deduplication: Duplicate extracted values are automatically removed
  • Enhanced Settings UI: Improved pattern management with field sections, Esc key handling, and better visual organization
  • Backward Compatibility: Existing callUrl and callType fields continue to work unchanged

Features

Pattern Types

  • Contains: Simple text matching (e.g., "zoom.us")
  • Regex: Full regular expression support for complex patterns

Default Patterns (Backward Compatible)

  1. Google Meet (GOOGLE-CONFERENCE - contains) → "Video Call URLs"
  2. Zoom (zoom.us - contains) → "Video Call URLs"
  3. Skype (https://join\.skype\.com/[a-zA-Z0-9]+ - regex) → "Video Call URLs"
  4. Microsoft Teams (https://teams\.microsoft\.com/l/meetup-join/[^>]+ - regex) → "Video Call URLs"

Field Organization

  • Field Sections: Group related patterns (e.g., all video call patterns in "Video Call URLs")
  • Custom Fields: Create unlimited field types for any data extraction needs
  • Flexible Naming: Use descriptive field names like "Phone Numbers", "Meeting IDs", "Links"

Settings UI Improvements

  • Field Section Management: Create, edit, and delete field sections
  • Pattern Management: Add, edit, delete, and reorder patterns within sections
  • Visual Organization: Field sections are clearly separated and organized
  • Reset All Button: Properly positioned reset button that affects all patterns
  • User Experience: Esc key handling for modal dialogs
  • Real-time Validation: Regex patterns validated as you type

Data Access

Legacy API (Backward Compatible)

event.callUrl   // First video call URL (unchanged)
event.callType  // "Video Call" when URL exists (unchanged)

New Generic API (Recommended)

event.extractedFields["Video Call URLs"]  // Array of all video URLs (deduplicated)
event.extractedFields["Phone Numbers"]    // Array of extracted phone numbers
event.extractedFields["Meeting IDs"]      // Array of meeting IDs
event.extractedFields["Custom Field"]     // Any custom field you configure

Use Cases

  • Video Calls: Extract URLs from Google Meet, Zoom, WebEx, GoToMeeting, Jitsi, etc.
  • Contact Info: Extract phone numbers, email addresses, contact names
  • Meeting Metadata: Extract meeting IDs, passcodes, participant limits
  • Document Links: Extract document URLs, share links, resource URLs
  • Custom Data: Extract any structured data from event descriptions

Technical Details

  • Backward Compatible: Existing templates using callUrl/callType continue to work
  • Migration Logic: Automatic settings upgrade from old video call extraction format
  • Deduplication: Set-based deduplication prevents repeated extracted values
  • Test Coverage: All existing tests updated and passing with new plural field names
  • Type Safety: Full TypeScript support for field extraction patterns

Migration Path

Existing users:

  • All existing functionality continues to work unchanged
  • Old callUrl and callType properties still populated from "Video Call URLs" field
  • Can optionally migrate to extractedFields API for more flexibility

New users:

  • Start with default video call extraction patterns
  • Can immediately extend to extract any field type
  • Modern extractedFields API available from day one

🤖 Generated with Claude Code

Co-Authored-By: Claude [email protected]

Summary by CodeRabbit

  • New Features

    • Configurable field extraction from calendar events with pattern-based matching, defaults for major video providers, multi-value support, and backward-compatible call URL/type.
    • Expanded settings UI to manage calendars, output format, and extraction patterns (add/edit/reorder/reset), with modals and unsaved-change protection.
    • Events now expose extracted fields for richer template usage, plus a templater example helper.
  • Documentation

    • README overhauled with detailed setup, usage, field extraction guidance, and migration notes.
  • Style

    • New styles for the settings modal, section headers, notes, and tips.

@muness muness self-assigned this Sep 26, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 26, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds a pattern-driven field extraction system for calendar events, rewrites README with extraction docs, replaces extractMeetingInfo with extractFields, introduces fieldExtraction settings and defaults, updates settings UI to manage patterns, migrates legacy settings, propagates extractedFields to events, and adjusts tests accordingly.

Changes

Cohort / File(s) Summary
Documentation
README.md
Substantially rewritten; added "Field Extraction" section, default provider patterns, pattern configuration (contains/regex/priority), access patterns, migration guidance, and expanded usage examples.
Extraction Logic
src/icalUtils.ts, tests/icalUtils.test.ts
Replaced extractMeetingInfo with extractFields(e, patterns?) returning Record<string,string[]>; added pattern matching (contains/regex), helpers (findPatternMatches, matchTextForPattern), deduplication, and tests updated to use DEFAULT_FIELD_EXTRACTION_PATTERNS and new expectations.
Settings Schema & Defaults
src/settings/ICSSettings.ts
Added FieldExtractionPattern interface and fieldExtraction to ICSSettings; introduced DEFAULT_FIELD_EXTRACTION_PATTERNS and set fieldExtraction defaults in DEFAULT_SETTINGS.
Main Integration & Migration
src/main.ts
Uses DEFAULT_FIELD_EXTRACTION_PATTERNS; calls extractFields with enabled/patterns; derives legacy callUrl/callType for backward compatibility; adds extractedFields to emitted IEvent; migrates legacy videoCallExtraction into new fieldExtraction schema and persists defaults.
Public Types
src/IEvent.ts
Added extractedFields: Record<string,string[]> to IEvent interface (backward-compatible callUrl/callType retained).
Settings UI & Modals
src/settings/ICSSettingsTab.ts
Replaced simple settings UI with comprehensive Field Extraction editor: create/edit/delete patterns and field sections, priority management, validation modals, templater example modal, defaults reset, and improved unsaved-change handling.
Styling
styles.css
Added CSS rules supporting the new Settings modal and field extraction UI (visual/presentational only).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Plugin as Plugin (main.ts)
  participant SettingsStore as Settings (ICSSettings)
  participant UI as Settings UI (ICSSettingsTab)
  participant Extractor as extractFields (icalUtils)

  rect rgba(200,230,255,0.18)
    Plugin->>SettingsStore: loadSettings()
    SettingsStore-->>Plugin: settings (migrated if needed)
    Plugin->>SettingsStore: save migrated defaults (if applied)
  end

  User->>UI: open settings
  UI-->>User: render fieldExtraction UI
  User->>UI: add/edit/delete patterns
  UI->>SettingsStore: save fieldExtraction changes

  rect rgba(230,255,230,0.18)
    Plugin->>Extractor: extractFields(event, patterns)
    Extractor->>Extractor: sort by priority, apply contains/regex, collect matches
    Extractor-->>Plugin: extractedFields (Record<string,string[]>)
    Plugin->>Plugin: derive callUrl/callType (back-compat), attach to IEvent
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Feature: Field Extraction #196 — Implements similar pattern-driven field extraction and settings UI changes; strong code-level overlap and likely shared design decisions.

Poem

I twitch my whiskers, sniff the text,
Patterned trails where links connect.
Regex hops and contains-beats,
I fetch the calls from calendar treats.
Settings burrowed, defaults bright—
Hooray! The rabbit found the right invite. 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “WIP Field Extraction” is vague and does not clearly describe the main change of adding configurable video call URL extraction patterns and UI. It fails to specify the actual field being extracted or reference video call URIs, making it hard for reviewers to understand the primary purpose at a glance. Please rename the pull request to clearly reflect the main feature, for example “Add configurable video call URL extraction patterns and settings UI” so that the title concisely summarizes the core enhancement.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee3e02 and 243881e.

📒 Files selected for processing (8)
  • README.md (1 hunks)
  • src/IEvent.ts (1 hunks)
  • src/icalUtils.ts (1 hunks)
  • src/main.ts (5 hunks)
  • src/settings/ICSSettings.ts (2 hunks)
  • src/settings/ICSSettingsTab.ts (1 hunks)
  • styles.css (1 hunks)
  • tests/icalUtils.test.ts (2 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

@muness muness added the enhancement New feature or request label Sep 26, 2025
@muness
Copy link
Member Author

muness commented Sep 26, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Sep 26, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
src/icalUtils.ts (1)

15-20: Avoid mutating caller-supplied pattern arrays

patterns.sort(...) mutates the array that was passed in, which means every call reorders this.data.videoCallExtraction.patterns (and the exported defaults when used directly), creating surprising statefulness. Copy the array before sorting so extraction stays side-effect free.

-  const sortedPatterns = patterns.sort((a, b) => a.priority - b.priority);
+  const sortedPatterns = [...patterns].sort((a, b) => a.priority - b.priority);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4952f40 and 0ee3e02.

📒 Files selected for processing (6)
  • README.md (1 hunks)
  • src/icalUtils.ts (1 hunks)
  • src/main.ts (3 hunks)
  • src/settings/ICSSettings.ts (2 hunks)
  • src/settings/ICSSettingsTab.ts (1 hunks)
  • tests/icalUtils.test.ts (6 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
README.md

164-164: Hard tabs
Column: 1

(MD010, no-hard-tabs)


165-165: Hard tabs
Column: 1

(MD010, no-hard-tabs)


166-166: Hard tabs
Column: 1

(MD010, no-hard-tabs)


167-167: Hard tabs
Column: 1

(MD010, no-hard-tabs)


168-168: Hard tabs
Column: 1

(MD010, no-hard-tabs)


169-169: Hard tabs
Column: 1

(MD010, no-hard-tabs)


170-170: Hard tabs
Column: 1

(MD010, no-hard-tabs)


171-171: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🪛 ast-grep (0.39.5)
src/icalUtils.ts

[warning] 60-60: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(pattern.pattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

src/settings/ICSSettingsTab.ts

[warning] 765-765: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(this.pattern.pattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 786-786: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(this.pattern.pattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 323-325: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: divSponsor.innerHTML = <br/><hr/>A scratch my own itch project by <a href="https://muness.com/" target='_blank'>muness</a>.<br/> <a href='https://www.buymeacoffee.com/muness' target='_blank'><img height="36" src='https://cdn.buymeacoffee.com/uploads/profile_pictures/default/79D6B5/MC.png' border='0' alt='Buy Me a Book' /></a>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 323-325: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: divSponsor.innerHTML = <br/><hr/>A scratch my own itch project by <a href="https://muness.com/" target='_blank'>muness</a>.<br/> <a href='https://www.buymeacoffee.com/muness' target='_blank'><img height="36" src='https://cdn.buymeacoffee.com/uploads/profile_pictures/default/79D6B5/MC.png' border='0' alt='Buy Me a Book' /></a>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)

🔇 Additional comments (3)
tests/icalUtils.test.ts (1)

104-145: Tests now exercise configurable pattern flow

Passing DEFAULT_VIDEO_CALL_PATTERNS into extractMeetingInfo keeps the spec aligned with the new signature and validates the default pattern set end-to-end. Thanks for wiring this up.

README.md (2)

162-171: Replace hard tabs in Full Calendar example

Lines [164-171] contain hard tabs, which trip the markdownlint MD010 rule in the static analysis hints. Swapping them for spaces keeps the lint pipeline green without changing the example’s intent. Apply something like:

-	  const start = moment.unix(event.utime)
-	  const [endHours, endMinutes] = event.endTime.split(":")
-	  return {
-	      start: start.toDate(),
-	      end: start.set({hour: endHours, minute: endMinutes}).toDate(),
-	      title: event.summary,
-	    }
-	}
+      const start = moment.unix(event.utime)
+      const [endHours, endMinutes] = event.endTime.split(":")
+      return {
+        start: start.toDate(),
+        end: start.set({hour: endHours, minute: endMinutes}).toDate(),
+        title: event.summary,
+      }
+    }

[ suggest_optional_refactor ]
Based on static analysis hints


223-223: Correct “Obdisian” typo

Line [223] introduces a misspelling of “Obsidian”. Suggested fix:

-5. copy the `dist/main.js` (or `dist/main-debug.js` if you want the un-minified version) to your Obdisian vault plugin folder (`cp dist/main.js <vault>/.obsidian/plugins/ics/main.js`).
+5. copy the `dist/main.js` (or `dist/main-debug.js` if you want the un-minified version) to your Obsidian vault plugin folder (`cp dist/main.js <vault>/.obsidian/plugins/ics/main.js`).

Likely an incorrect or invalid review comment.


See [advanced Templated usage example](https://github.com/cloud-atlas-ai/obsidian-ics/discussions/74#discussion-5779931) for an example that demonstrates more features.

You can see the available fields an the [Event interface](https://github.com/cloud-atlas-ai/obsidian-ics/blob/master/src/IEvent.ts).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo: “an the” → “in the”

Line [152] reads “an the”. Small doc polish, but worth fixing:

-You can see the available fields an the [Event interface](https://github.com/cloud-atlas-ai/obsidian-ics/blob/master/src/IEvent.ts).
+You can see the available fields in the [Event interface](https://github.com/cloud-atlas-ai/obsidian-ics/blob/master/src/IEvent.ts).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
You can see the available fields an the [Event interface](https://github.com/cloud-atlas-ai/obsidian-ics/blob/master/src/IEvent.ts).
You can see the available fields in the [Event interface](https://github.com/cloud-atlas-ai/obsidian-ics/blob/master/src/IEvent.ts).
🤖 Prompt for AI Agents
In README.md around line 152, there is a typo "an the" in the sentence; replace
"an the" with "in the" so the line reads "You can see the available fields in
the [Event
interface](https://github.com/cloud-atlas-ai/obsidian-ics/blob/master/src/IEvent.ts)."

src/main.ts Outdated
Comment on lines 269 to 278
this.data.videoCallExtraction = {
enabled: true,
patterns: [...DEFAULT_VIDEO_CALL_PATTERNS]
};
needsSave = true;
} else {
// Ensure patterns array exists
if (!this.data.videoCallExtraction.patterns) {
this.data.videoCallExtraction.patterns = [...DEFAULT_VIDEO_CALL_PATTERNS];
needsSave = true;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Deep clone video-call defaults during migration

This migration still copies DEFAULT_VIDEO_CALL_PATTERNS by reference—[...DEFAULT_VIDEO_CALL_PATTERNS] creates a new array but keeps the same pattern objects. Editing or reordering patterns in the settings UI will therefore mutate the exported defaults, so “reset to defaults” no longer restores the original values and those mutations get saved back as if they were defaults. Please clone the pattern objects before storing them.

-        patterns: [...DEFAULT_VIDEO_CALL_PATTERNS]
+        patterns: DEFAULT_VIDEO_CALL_PATTERNS.map(pattern => ({ ...pattern }))

The same adjustment is needed in every branch where we hydrate videoCallExtraction.patterns.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main.ts around lines 269 to 278, the migration copies
DEFAULT_VIDEO_CALL_PATTERNS by shallow-cloning the array which keeps references
to the same pattern objects; change assignments so you deep-clone the pattern
objects (e.g. map over DEFAULT_VIDEO_CALL_PATTERNS and create new objects for
each pattern) before storing them into this.data.videoCallExtraction.patterns,
and apply the same deep-clone approach to every other branch in this file where
videoCallExtraction.patterns is hydrated during migration.

Comment on lines 91 to 94
videoCallExtraction: {
enabled: true,
patterns: DEFAULT_VIDEO_CALL_PATTERNS
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Prevent default video-call patterns from being mutated at runtime

DEFAULT_SETTINGS.videoCallExtraction.patterns currently points straight at DEFAULT_VIDEO_CALL_PATTERNS. Because loadSettings does a shallow Object.assign, the plugin state shares that same array/object. As soon as we call extractMeetingInfo (which sorts in place) or the user edits/reorders a pattern, we mutate the exported defaults. “Reset to defaults” will then reapply the already-mutated data, and future migrations treat those mutations as canonical defaults. Please deep-clone the defaults before storing them (and mirror that change in the migration code so every entry is copied).

-        patterns: DEFAULT_VIDEO_CALL_PATTERNS
+        patterns: DEFAULT_VIDEO_CALL_PATTERNS.map(pattern => ({ ...pattern }))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
videoCallExtraction: {
enabled: true,
patterns: DEFAULT_VIDEO_CALL_PATTERNS
}
videoCallExtraction: {
enabled: true,
patterns: DEFAULT_VIDEO_CALL_PATTERNS.map(pattern => ({ ...pattern }))
}
🤖 Prompt for AI Agents
In src/settings/ICSSettings.ts around lines 91-94,
DEFAULT_SETTINGS.videoCallExtraction.patterns currently references
DEFAULT_VIDEO_CALL_PATTERNS directly which allows runtime mutations to alter the
exported defaults; change the assignment to deep-clone
DEFAULT_VIDEO_CALL_PATTERNS when building DEFAULT_SETTINGS (use structuredClone
or JSON.parse(JSON.stringify(...))) so the settings get their own copy, and
update the migration code that copies/initializes videoCallExtraction patterns
to also deep-clone each entry rather than copying references so migrations don’t
propagate mutated defaults.

Comment on lines 78 to 86
if (!this.plugin.data.videoCallExtraction?.patterns) {
if (!this.plugin.data.videoCallExtraction) {
this.plugin.data.videoCallExtraction = {
enabled: true,
patterns: DEFAULT_VIDEO_CALL_PATTERNS
};
} else {
this.plugin.data.videoCallExtraction.patterns = DEFAULT_VIDEO_CALL_PATTERNS;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Avoid mutating DEFAULT_VIDEO_CALL_PATTERNS at runtime

DEFAULT_VIDEO_CALL_PATTERNS is being stored by reference in user settings. As soon as a user adds/edits/deletes a pattern, the constant array (and therefore the defaults shipped with the plugin) get mutated, which breaks “Reset to Defaults” and can leak user-specific patterns into future sessions/migrations. Please hydrate videoCallExtraction.patterns with deep copies instead of the shared constant.

-        this.plugin.data.videoCallExtraction = {
-          enabled: true,
-          patterns: DEFAULT_VIDEO_CALL_PATTERNS
-        };
+        this.plugin.data.videoCallExtraction = {
+          enabled: true,
+          patterns: DEFAULT_VIDEO_CALL_PATTERNS.map((pattern) => ({ ...pattern })),
+        };
       } else {
-        this.plugin.data.videoCallExtraction.patterns = DEFAULT_VIDEO_CALL_PATTERNS;
+        this.plugin.data.videoCallExtraction.patterns = DEFAULT_VIDEO_CALL_PATTERNS.map((pattern) => ({ ...pattern }));
       }
🤖 Prompt for AI Agents
In src/settings/ICSSettingsTab.ts around lines 78–86, the code assigns
DEFAULT_VIDEO_CALL_PATTERNS by reference into
this.plugin.data.videoCallExtraction.patterns, which lets runtime edits mutate
the shared constant; replace those assignments with a deep copy (e.g.,
structuredClone(DEFAULT_VIDEO_CALL_PATTERNS) or
JSON.parse(JSON.stringify(DEFAULT_VIDEO_CALL_PATTERNS)) or lodash/cloneDeep) in
both branches so the settings hold an independent copy and subsequent user edits
do not modify the module-level constant.

@muness muness changed the title WIP Permissive Video Call URI Extraction WIP Field Extraction Sep 26, 2025
@muness muness marked this pull request as ready for review September 26, 2025 19:17
@muness muness changed the title WIP Field Extraction Feature: Field Extraction Sep 26, 2025
@muness muness merged commit 147b7b3 into master Sep 26, 2025
1 check was pending
@muness muness deleted the feature/configurable-video-call-urls branch September 26, 2025 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants