Skip to content

Commit 6701b64

Browse files
committed
refactoring
1 parent b7d3902 commit 6701b64

30 files changed

Lines changed: 822 additions & 1921 deletions

.claude/settings.local.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"WebSearch"
5+
]
6+
}
7+
}

.github/workflows/release.yml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: Release Module
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'module.json'
9+
10+
jobs:
11+
build:
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: write
15+
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 2
21+
22+
- name: Check if version changed
23+
id: check_version
24+
run: |
25+
CURRENT_VERSION=$(jq -r '.version' module.json)
26+
PREVIOUS_VERSION=$(git show HEAD~1:module.json | jq -r '.version')
27+
28+
echo "Current version: $CURRENT_VERSION"
29+
echo "Previous version: $PREVIOUS_VERSION"
30+
31+
if [ "$CURRENT_VERSION" != "$PREVIOUS_VERSION" ]; then
32+
echo "changed=true" >> $GITHUB_OUTPUT
33+
echo "VERSION=$CURRENT_VERSION" >> $GITHUB_OUTPUT
34+
echo "Version changed from $PREVIOUS_VERSION to $CURRENT_VERSION"
35+
else
36+
echo "changed=false" >> $GITHUB_OUTPUT
37+
echo "Version unchanged, skipping release"
38+
fi
39+
40+
- name: Check if tag exists
41+
if: steps.check_version.outputs.changed == 'true'
42+
id: check_tag
43+
run: |
44+
if git rev-parse "v${{ steps.check_version.outputs.VERSION }}" >/dev/null 2>&1; then
45+
echo "exists=true" >> $GITHUB_OUTPUT
46+
echo "Tag v${{ steps.check_version.outputs.VERSION }} already exists, skipping release"
47+
else
48+
echo "exists=false" >> $GITHUB_OUTPUT
49+
fi
50+
51+
- name: Create module package
52+
if: steps.check_version.outputs.changed == 'true' && steps.check_tag.outputs.exists == 'false'
53+
run: |
54+
mkdir -p sleek-chat
55+
56+
# Copy necessary files and directories
57+
cp module.json sleek-chat/
58+
59+
# Copy directories
60+
cp -r scripts sleek-chat/
61+
cp -r styles sleek-chat/
62+
63+
# Create zip file (named module.zip to match module.json)
64+
cd sleek-chat
65+
zip -r ../module.zip .
66+
cd ..
67+
68+
- name: Create Release
69+
if: steps.check_version.outputs.changed == 'true' && steps.check_tag.outputs.exists == 'false'
70+
uses: softprops/action-gh-release@v1
71+
with:
72+
tag_name: v${{ steps.check_version.outputs.VERSION }}
73+
name: Release v${{ steps.check_version.outputs.VERSION }}
74+
files: |
75+
module.json
76+
module.zip
77+
body: |
78+
## Sleek Chat v${{ steps.check_version.outputs.VERSION }}
79+
80+
### Installation
81+
Install directly from Foundry VTT using the manifest URL, or:
82+
1. Download `module.zip`
83+
2. Extract to your Foundry VTT `Data/modules/` directory
84+
3. Enable the module in your world's module settings
85+
env:
86+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CLAUDE.md

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
**Sleek Chat** is a Foundry VTT module (v12+) that provides a minimalist dice rolling toolbar and chat interface. It appears only when the sidebar is collapsed, reducing UI clutter for story-focused games.
8+
9+
**Critical**: This module has NO build process. There is no package.json, webpack, or any bundler. All JavaScript is native ES6 modules, CSS is plain CSS (no preprocessing), and templates are Handlebars files loaded at runtime.
10+
11+
## Development Workflow
12+
13+
### Making Changes
14+
1. Edit files directly in the module folder
15+
2. Refresh Foundry VTT in browser to see changes
16+
3. No compilation, build, or preprocessing step needed
17+
4. CSS is automatically loaded - do NOT try to compile or build it
18+
19+
### Testing
20+
- Enable "Debug Mode" in module settings for console logging
21+
- Use the `debugLog()` function from `scripts/sleek-chat-debug.js` for conditional logging
22+
- Test with sidebar collapsed and expanded states
23+
- Test with both GM and player accounts for permission-based features
24+
25+
### File Editing
26+
- ALWAYS use `foundry.applications.handlebars.loadTemplates()` (namespaced), NOT the deprecated global `loadTemplates()`
27+
- Preserve exact indentation when editing (mix of tabs/spaces exists)
28+
- Templates use Handlebars syntax (.hbs files)
29+
30+
## Architecture
31+
32+
### Module Loading Order (from module.json)
33+
1. **scripts/settings.js** - Registers all game settings in `Hooks.once('init')`
34+
2. **scripts/sleek-chat-debug.js** - Debug utility (`debugLog()` function)
35+
3. **scripts/main.js** - Main UI logic, dice rolling, visibility control
36+
4. **scripts/recent-message-display.js** - Message history and navigation
37+
38+
### Key Design Patterns
39+
40+
#### Hook-Based Architecture
41+
The module uses Foundry's Hook system extensively:
42+
- `Hooks.once('init')` - Register settings before game loads
43+
- `Hooks.on('ready')` - Initialize UI after everything loads
44+
- `Hooks.on('renderChatLog')` - Inject custom toolbar into chat
45+
- `Hooks.on('createChatMessage')` - React to new messages
46+
- `Hooks.on('updateSetting')` - Respond to setting changes
47+
48+
#### Settings System
49+
Two types of settings:
50+
- **Client-side** (`scope: "client"`): Personal preferences (opacity, colors, debug mode)
51+
- **World-level** (`scope: "world"`): GM-controlled (hide buttons, dice ranges)
52+
53+
Settings use `onChange` callbacks for immediate UI updates. Some require reload dialogs for complex changes.
54+
55+
#### Static Class Pattern
56+
`RecentMessageDisplay` is a static class with methods:
57+
- `init()` - Initialize message display system
58+
- `addMessageToHistory(messageId)` - Track new messages
59+
- `updateRecentMessage(messageId)` - Display specific message
60+
- `navigateMessages(direction)` - Navigate through last 50 messages
61+
- `validateMessageIds()` - Clean up deleted message IDs
62+
63+
### Core Features Implementation
64+
65+
#### Conditional UI Display
66+
Uses MutationObserver to watch sidebar collapse state:
67+
```javascript
68+
const observer = new MutationObserver(() => updateVisibility());
69+
observer.observe(document.getElementById('sidebar'), {
70+
attributes: true,
71+
attributeFilter: ['class']
72+
});
73+
```
74+
75+
#### Dice Rolling
76+
- Click to add dice, right-click to remove
77+
- Builds roll formula (e.g., "2d20kh + 3" for advantage)
78+
- Creates `new Roll(formula).evaluate()`
79+
- Integrates with Dice So Nice if available
80+
- Results color-coded based on configurable ranges per die type
81+
82+
#### Message Display
83+
- Shows most recent chat message in compact view
84+
- Fade-out effects with configurable timing/opacity
85+
- Hover restores full opacity
86+
- Navigation through message history
87+
- Message validation handles deleted messages
88+
89+
#### Navigation Button Hiding
90+
- Dynamically hide sidebar tabs based on settings
91+
- "Apply only to Players" option for GM
92+
- "Hide Always" hides even when sidebar expanded
93+
- Creates dynamic settings for new tabs from other modules
94+
95+
### Data Flow Examples
96+
97+
**Settings Change Flow:**
98+
```
99+
game.settings.set()
100+
→ onChange callback
101+
→ Immediate UI update OR reload dialog
102+
```
103+
104+
**Dice Roll Flow:**
105+
```
106+
User clicks "Roll!"
107+
→ Build formula from selected dice/modifiers
108+
→ new Roll(formula).evaluate()
109+
→ Dice So Nice animation (if available)
110+
→ Render templates/common-roll.hbs
111+
→ ChatMessage.create() with roll data
112+
```
113+
114+
**Message Creation Flow:**
115+
```
116+
ChatMessage.create()
117+
→ Hook: 'createChatMessage'
118+
→ RecentMessageDisplay.addMessageToHistory()
119+
→ RecentMessageDisplay.updateRecentMessage()
120+
→ DOM updated + fade timer started
121+
→ playPingSound() if enabled
122+
```
123+
124+
## File Structure
125+
126+
```
127+
sleek-chat/
128+
├── scripts/
129+
│ ├── main.js # Main logic: dice rolling, UI visibility, nav hiding
130+
│ ├── settings.js # All game.settings.register() calls
131+
│ ├── recent-message-display.js # Message history management
132+
│ └── sleek-chat-debug.js # debugLog() utility
133+
├── styles/
134+
│ └── styles.css # All styles (no preprocessing!)
135+
├── templates/
136+
│ ├── dice-toolbar.hbs # Main UI toolbar
137+
│ ├── common-roll.hbs # Dice roll result display
138+
│ └── custom-chat-card.hbs # Custom chat card
139+
├── ui/ # SVG dice icons and sound file
140+
├── module.json # Foundry module manifest
141+
└── sleek-chat.zip # Distribution package
142+
```
143+
144+
## Key Functions and Exports
145+
146+
### scripts/main.js
147+
- `applyChatBaseContainerOpacity()` - Set container opacity with hover effects
148+
- `applySeeOnlyChat(seeOnlyChat)` - Toggle chat-only mode (hide dice)
149+
- `applyNavButtonHiding()` - Show/hide navigation buttons
150+
- `applyDiceColorFilter(colorName)` - Apply CSS filter for dice colors
151+
- `parseDiceRanges()` - Parse fumble/normal/critical ranges from settings
152+
153+
### scripts/recent-message-display.js
154+
- `RecentMessageDisplay.init()` - Initialize on ready
155+
- `RecentMessageDisplay.addMessageToHistory(messageId)` - Track new message
156+
- `RecentMessageDisplay.updateRecentMessage(messageId)` - Display message
157+
- `RecentMessageDisplay.navigateMessages(direction)` - Navigate history
158+
- `RecentMessageDisplay.validateMessageIds()` - Clean deleted messages
159+
- `applyMessageFadeOutSettings()` - Apply fade settings
160+
161+
### scripts/sleek-chat-debug.js
162+
- `debugLog(...args)` - Conditional console.log based on debug mode setting
163+
164+
## Important Implementation Notes
165+
166+
### Templates
167+
- Use `renderTemplate('modules/sleek-chat/templates/file.hbs', data)`
168+
- Template data objects must match Handlebars variable names
169+
- Templates are loaded via `foundry.applications.handlebars.loadTemplates()` in ready hook
170+
171+
### CSS
172+
- Single file: `styles/styles.css`
173+
- Uses CSS custom properties: `--dice-filter` for color changes
174+
- Applied via module.json, no manual loading needed
175+
- Auto-loaded by Foundry, no build step
176+
177+
### DOM Manipulation
178+
- Heavy use of jQuery for animations: `$().fadeTo()`, `$().addClass()`
179+
- Direct DOM queries: `document.querySelector()`, `document.querySelectorAll()`
180+
- Event delegation for dynamic content
181+
182+
### Foundry API Integration
183+
- `game.settings.get/set()` - All configuration
184+
- `game.user.isGM` - Permission checks
185+
- `game.messages` - Message history access
186+
- `ChatMessage.create()` - Create chat messages
187+
- `Roll` - Dice rolling engine
188+
- `ui.sidebar` - Sidebar state
189+
190+
### Version Management
191+
- Current version: 1.4.1
192+
- Update version in module.json when releasing
193+
- Update CHANGELOG.md with changes
194+
- Recreate sleek-chat.zip with updated files
195+
- Commit and push to GitHub main branch
196+
197+
## Common Patterns
198+
199+
### Adding a New Setting
200+
1. Register in `scripts/settings.js` within `Hooks.once('init')`
201+
2. Use appropriate scope: `"client"` or `"world"`
202+
3. Add `onChange` callback for immediate updates if needed
203+
4. Import and call update functions from main.js if needed
204+
205+
### Adding a New Die Type
206+
1. Add SVG icons to `ui/` folder (normal and filled versions)
207+
2. Update `templates/dice-toolbar.hbs` with new die button
208+
3. Add setting in `scripts/settings.js` for result ranges
209+
4. Update `parseDiceRanges()` in `scripts/main.js`
210+
211+
### Modifying UI Templates
212+
1. Edit the .hbs file in `templates/`
213+
2. Ensure data object passed to `renderTemplate()` has matching properties
214+
3. Refresh Foundry to see changes
215+
4. No compilation needed
216+
217+
## Integration Points
218+
219+
### With Foundry Core
220+
- Settings API for all configuration persistence
221+
- Hook system for event-driven architecture
222+
- ChatMessage API for message creation
223+
- Roll API for dice mechanics
224+
- Sidebar API for UI state
225+
226+
### With Other Modules
227+
- **Dice So Nice**: Optional 3D dice visualization integration
228+
- **Dynamic sidebar modules**: Auto-creates hide settings for new navigation tabs
229+
- Extensible for system-specific chat buttons
230+
231+
## Debugging
232+
233+
- Enable "Debug Mode" in module settings
234+
- All debug output uses `debugLog()` function
235+
- Check browser console for log messages
236+
- Debug messages indicate: settings changes, opacity adjustments, message navigation, button visibility logic
237+
238+
## Known Limitations
239+
240+
- Some game systems with custom chat buttons may have interaction issues
241+
- Users should report issues at: https://github.com/mordachai/sleek-chat/issues

module.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"id": "sleek-chat",
33
"title": "Sleek Chat",
4-
"description": "A minimalist dice rolling toolbar that integrates seamlessly with the Foundry VTT chat, focusing on a clean and uncluttered interface.",
5-
"version": "1.4.1",
4+
"description": "Minimalist chat popout enhancements for Foundry VTT v13+. Shows only the current message with navigation controls and customizable opacity.",
5+
"version": "2.0.0",
66
"compatibility": {
77
"minimum": "12",
8-
"verified": "12"
8+
"verified": "13"
99
},
1010
"authors": [
1111
{
@@ -19,8 +19,10 @@
1919
"esmodules": [
2020
"scripts/settings.js",
2121
"scripts/sleek-chat-debug.js",
22-
"scripts/main.js",
23-
"scripts/recent-message-display.js"
22+
"scripts/popout-opacity.js",
23+
"scripts/popout-message-manager.js",
24+
"scripts/popout-chat.js",
25+
"scripts/main.js"
2426
],
2527
"url": "https://github.com/mordachai/sleek-chat",
2628
"manifest": "https://github.com/mordachai/sleek-chat/raw/main/module.json",

0 commit comments

Comments
 (0)