From 9c34bf73c6a79c59369862bcd5fae3946c911c3c Mon Sep 17 00:00:00 2001 From: syui Date: Sat, 14 Jun 2025 15:47:39 +0900 Subject: [PATCH] fix css --- my-blog/static/css/style.css | 60 ++-- my-blog/static/js/ask-ai.js | 360 +++++++++++++++++++++++ my-blog/static/js/theme.js | 94 ++++++ my-blog/templates/base.html | 426 ++-------------------------- my-blog/templates/index.html | 2 +- my-blog/templates/post-complex.html | 2 +- my-blog/templates/post-simple.html | 2 +- my-blog/templates/post.html | 2 +- 8 files changed, 515 insertions(+), 433 deletions(-) create mode 100644 my-blog/static/js/ask-ai.js create mode 100644 my-blog/static/js/theme.js diff --git a/my-blog/static/css/style.css b/my-blog/static/css/style.css index dff34c9..d9b1eb1 100644 --- a/my-blog/static/css/style.css +++ b/my-blog/static/css/style.css @@ -199,8 +199,8 @@ a.view-markdown:any-link { @media (max-width: 1000px) { .main-content { - padding: 20px !important; - max-width: 100% !important; + padding: 20px; + max-width: 100%; } } @@ -737,7 +737,6 @@ a.view-markdown:any-link { margin: 0 auto; margin-top: 48px; padding-top: 32px; - border-top: 1px solid #d1d9e0; } .comment-container { @@ -771,23 +770,24 @@ a.view-markdown:any-link { /* Responsive */ @media (max-width: 1000px) { .article-container { - grid-template-columns: 1fr !important; - gap: 24px !important; - max-width: 100% !important; - padding: 0px !important; - margin: 0 !important; + grid-template-columns: 1fr; + gap: 24px; + max-width: 100%; + padding: 0; + margin: 0; } } @media (max-width: 1000px) { .main-header { - padding: 12px 0 !important; + padding: 12px 0; } .header-content { - max-width: 100% !important; - padding: 0 20px !important; - grid-template-columns: 0 1fr auto !important; + max-width: 100%; + padding: 0 20px; + grid-template-columns: auto 1fr auto; + gap: 0; } /* Hide site title text on mobile */ @@ -795,17 +795,20 @@ a.view-markdown:any-link { display: none; } - /* Center logo on mobile */ + /* Left align logo on mobile */ .logo { - grid-column: 1 / 3; - justify-self: center; + grid-column: 1; + justify-self: left; padding: 5px; + display: flex; + justify-content: flex-start; + align-items: center; } /* Reduce logo size on mobile */ .logo .likeButton { - width: 40pt !important; - height: 40pt !important; + width: 40pt; + height: 40pt; } /* Position AI button on the right */ @@ -814,24 +817,17 @@ a.view-markdown:any-link { justify-self: end; } - /* Show only icon for Ask AI button on mobile */ + /* Ask AI button mobile style */ .ask-ai-btn { padding: 8px; min-width: 40px; justify-content: center; + font-size: 0; + gap: 0; } .ask-ai-btn .ai-icon { margin: 0; - } - - /* Hide AI button text on mobile, show only icon */ - .ask-ai-btn { - font-size: 0; - gap: 0px !important; - } - - .ask-ai-btn .ai-icon { font-size: 16px; } @@ -845,14 +841,14 @@ a.view-markdown:any-link { } .article-body pre { - margin: 16px 0 !important; - border-radius: 4px !important; - max-width: 100% !important; - overflow-x: auto !important; + margin: 16px 0; + border-radius: 4px; + max-width: 100%; + overflow-x: auto; } .article-body pre code { - padding: 20px 12px !important; + padding: 20px 12px; word-wrap: break-word; white-space: pre-wrap; } diff --git a/my-blog/static/js/ask-ai.js b/my-blog/static/js/ask-ai.js new file mode 100644 index 0000000..94f7ad5 --- /dev/null +++ b/my-blog/static/js/ask-ai.js @@ -0,0 +1,360 @@ +/** + * Ask AI functionality - Pure JavaScript, no jQuery dependency + */ +class AskAI { + constructor() { + this.isReady = false; + this.aiProfile = null; + this.init(); + } + + init() { + this.setupEventListeners(); + this.checkAuthOnLoad(); + } + + setupEventListeners() { + // Listen for AI ready signal + window.addEventListener('aiChatReady', () => { + this.isReady = true; + console.log('AI Chat is ready'); + }); + + // Listen for AI profile updates + window.addEventListener('aiProfileLoaded', (event) => { + this.aiProfile = event.detail; + console.log('AI profile loaded:', this.aiProfile); + this.updateButton(); + }); + + // Listen for AI responses + window.addEventListener('aiResponseReceived', (event) => { + this.handleAIResponse(event.detail); + }); + + // Keyboard shortcuts + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + this.hide(); + } + if (e.key === 'Enter' && e.target.id === 'aiQuestion' && !e.shiftKey) { + e.preventDefault(); + this.ask(); + } + }); + + // Monitor authentication changes + this.observeAuth(); + } + + toggle() { + const panel = document.getElementById('askAiPanel'); + const isVisible = panel.style.display !== 'none'; + + if (isVisible) { + this.hide(); + } else { + this.show(); + } + } + + show() { + const panel = document.getElementById('askAiPanel'); + panel.style.display = 'block'; + this.checkAuth(); + } + + hide() { + const panel = document.getElementById('askAiPanel'); + panel.style.display = 'none'; + } + + checkAuth() { + const userSections = document.querySelectorAll('.user-section'); + const isAuthenticated = userSections.length > 0; + + const authCheck = document.getElementById('authCheck'); + const chatForm = document.getElementById('chatForm'); + const chatHistory = document.getElementById('chatHistory'); + + if (isAuthenticated) { + authCheck.style.display = 'none'; + chatForm.style.display = 'block'; + chatHistory.style.display = 'block'; + + if (chatHistory.children.length === 0) { + this.showGreeting(); + } + + setTimeout(() => { + document.getElementById('aiQuestion').focus(); + }, 50); + } else { + authCheck.style.display = 'block'; + chatForm.style.display = 'none'; + chatHistory.style.display = 'none'; + } + } + + checkAuthOnLoad() { + setTimeout(() => { + this.checkAuth(); + }, 500); + } + + observeAuth() { + const observer = new MutationObserver(() => { + const userSections = document.querySelectorAll('.user-section'); + if (userSections.length > 0) { + this.checkAuth(); + observer.disconnect(); + } + }); + + observer.observe(document.body, { + childList: true, + subtree: true + }); + } + + updateButton() { + const button = document.getElementById('askAiButton'); + if (this.aiProfile && this.aiProfile.displayName) { + const textNode = button.childNodes[2]; + if (textNode) { + textNode.textContent = this.aiProfile.displayName; + } + } + } + + showGreeting() { + if (!this.aiProfile) return; + + const chatHistory = document.getElementById('chatHistory'); + const greetingDiv = document.createElement('div'); + greetingDiv.className = 'chat-message ai-message comment-style initial-greeting'; + + const avatarElement = this.aiProfile.avatar + ? `${this.aiProfile.displayName}` + : 'πŸ€–'; + + greetingDiv.innerHTML = ` +
+
${avatarElement}
+ +
+
+ Hello! I'm an AI assistant trained on this blog's content. I can answer questions about the articles, provide insights, and help you understand the topics discussed here. What would you like to know? +
+ `; + chatHistory.appendChild(greetingDiv); + } + + async ask() { + const question = document.getElementById('aiQuestion').value; + const chatHistory = document.getElementById('chatHistory'); + const askButton = document.getElementById('askButton'); + + if (!question.trim()) return; + + // Wait for AI to be ready + if (!this.isReady) { + await this.waitForReady(); + } + + // Disable button + askButton.disabled = true; + askButton.textContent = 'Posting...'; + + try { + // Add user message + this.addUserMessage(question); + + // Clear input + document.getElementById('aiQuestion').value = ''; + + // Show loading + this.showLoading(); + + // Post question + const event = new CustomEvent('postAIQuestion', { + detail: { question: question } + }); + window.dispatchEvent(event); + + } catch (error) { + this.showError('Sorry, I encountered an error. Please try again.'); + } finally { + askButton.disabled = false; + askButton.textContent = 'Ask'; + } + } + + waitForReady() { + return new Promise(resolve => { + const checkReady = setInterval(() => { + if (this.isReady) { + clearInterval(checkReady); + resolve(); + } + }, 100); + }); + } + + addUserMessage(question) { + const chatHistory = document.getElementById('chatHistory'); + const userSection = document.querySelector('.user-section'); + + let userAvatar = 'πŸ‘€'; + let userDisplay = 'You'; + let userHandle = 'user'; + + if (userSection) { + const avatarImg = userSection.querySelector('.user-avatar'); + const displayName = userSection.querySelector('.user-display-name'); + const handle = userSection.querySelector('.user-handle'); + + if (avatarImg && avatarImg.src) { + userAvatar = `${displayName?.textContent || 'User'}`; + } + if (displayName?.textContent) { + userDisplay = displayName.textContent; + } + if (handle?.textContent) { + userHandle = handle.textContent.replace('@', ''); + } + } + + const questionDiv = document.createElement('div'); + questionDiv.className = 'chat-message user-message comment-style'; + questionDiv.innerHTML = ` +
+
${userAvatar}
+ +
+
${question}
+ `; + chatHistory.appendChild(questionDiv); + } + + showLoading() { + const chatHistory = document.getElementById('chatHistory'); + const loadingDiv = document.createElement('div'); + loadingDiv.className = 'ai-loading-simple'; + loadingDiv.innerHTML = ` + + θ€ƒγˆγ¦γ„γΎγ™ + + `; + chatHistory.appendChild(loadingDiv); + } + + showError(message) { + const chatHistory = document.getElementById('chatHistory'); + this.removeLoading(); + + const errorDiv = document.createElement('div'); + errorDiv.className = 'chat-message error-message comment-style'; + errorDiv.innerHTML = ` +
+
⚠️
+ +
+
${message}
+ `; + chatHistory.appendChild(errorDiv); + } + + removeLoading() { + const loadingMsg = document.querySelector('.ai-loading-simple'); + if (loadingMsg) { + loadingMsg.remove(); + } + } + + handleAIResponse(responseData) { + const chatHistory = document.getElementById('chatHistory'); + this.removeLoading(); + + const aiProfile = responseData.aiProfile; + if (!aiProfile || !aiProfile.handle || !aiProfile.displayName) { + console.error('AI profile data is missing'); + return; + } + + const timestamp = new Date(responseData.timestamp || Date.now()); + const avatarElement = aiProfile.avatar + ? `${aiProfile.displayName}` + : 'πŸ€–'; + + const answerDiv = document.createElement('div'); + answerDiv.className = 'chat-message ai-message comment-style'; + answerDiv.innerHTML = ` +
+
${avatarElement}
+ +
+
${responseData.answer}
+ `; + chatHistory.appendChild(answerDiv); + + // Limit chat history + this.limitChatHistory(); + } + + limitChatHistory() { + const chatHistory = document.getElementById('chatHistory'); + if (chatHistory.children.length > 10) { + chatHistory.removeChild(chatHistory.children[0]); + if (chatHistory.children.length > 0) { + chatHistory.removeChild(chatHistory.children[0]); + } + } + } +} + +// Initialize Ask AI when DOM is loaded +document.addEventListener('DOMContentLoaded', () => { + try { + window.askAIInstance = new AskAI(); + console.log('Ask AI initialized successfully'); + } catch (error) { + console.error('Failed to initialize Ask AI:', error); + } +}); + +// Global function for onclick +window.AskAI = { + toggle: function() { + console.log('AskAI.toggle called'); + if (window.askAIInstance) { + window.askAIInstance.toggle(); + } else { + console.error('Ask AI instance not available'); + } + }, + ask: function() { + console.log('AskAI.ask called'); + if (window.askAIInstance) { + window.askAIInstance.ask(); + } else { + console.error('Ask AI instance not available'); + } + } +}; \ No newline at end of file diff --git a/my-blog/static/js/theme.js b/my-blog/static/js/theme.js new file mode 100644 index 0000000..108587e --- /dev/null +++ b/my-blog/static/js/theme.js @@ -0,0 +1,94 @@ +/** + * Theme and visual effects - Pure CSS animations, no jQuery + */ +class Theme { + constructor() { + this.init(); + } + + init() { + this.setupParticleColors(); + this.setupLogoAnimations(); + } + + setupParticleColors() { + // Dynamic particle colors based on theme + const style = document.createElement('style'); + style.textContent = ` + /* Dynamic particle colors based on theme */ + .likeButton .particleLayer circle:nth-child(1), + .likeButton .particleLayer circle:nth-child(2) { + fill: var(--particle-color-1) !important; + } + + .likeButton .particleLayer circle:nth-child(3), + .likeButton .particleLayer circle:nth-child(4) { + fill: var(--particle-color-2) !important; + } + + .likeButton .particleLayer circle:nth-child(5), + .likeButton .particleLayer circle:nth-child(6), + .likeButton .particleLayer circle:nth-child(7) { + fill: var(--particle-color-3) !important; + } + + .likeButton .particleLayer circle:nth-child(8), + .likeButton .particleLayer circle:nth-child(9), + .likeButton .particleLayer circle:nth-child(10) { + fill: var(--particle-color-4) !important; + } + + .likeButton .particleLayer circle:nth-child(11), + .likeButton .particleLayer circle:nth-child(12), + .likeButton .particleLayer circle:nth-child(13), + .likeButton .particleLayer circle:nth-child(14) { + fill: var(--particle-color-5) !important; + } + + /* Reset initial animations but allow hover */ + .likeButton .syui { + animation: none; + } + + .likeButton .particleLayer { + animation: none; + } + + .likeButton .explosion { + animation: none; + } + + /* Enable hover animations from package */ + .likeButton:hover .syui, + .likeButton:hover path.syui { + animation: syuiDeluxeAnime 400ms forwards !important; + } + + .likeButton:hover .particleLayer { + animation: particleLayerAnime 800ms forwards !important; + } + + .likeButton:hover .explosion { + animation: explosionAnime 800ms forwards !important; + } + + /* Logo positioning */ + .logo .likeButton { + background: transparent !important; + display: block; + } + `; + document.head.appendChild(style); + } + + setupLogoAnimations() { + // Pure CSS animations are handled by the svg-animation-package.css + // This method is reserved for any future JavaScript-based enhancements + console.log('Logo animations initialized (CSS-based)'); + } +} + +// Initialize theme when DOM is loaded +document.addEventListener('DOMContentLoaded', () => { + new Theme(); +}); \ No newline at end of file diff --git a/my-blog/templates/base.html b/my-blog/templates/base.html index e4e8a76..22cbed1 100644 --- a/my-blog/templates/base.html +++ b/my-blog/templates/base.html @@ -7,7 +7,6 @@ - @@ -16,9 +15,6 @@ - - - {% include "oauth-assets.html" %} {% block head %}{% endblock %} @@ -28,34 +24,33 @@

{{ config.title }}

- - @@ -63,21 +58,18 @@
- + @@ -98,367 +90,7 @@

Β© {{ config.author }}

- - - - + + \ No newline at end of file diff --git a/my-blog/templates/index.html b/my-blog/templates/index.html index 7dc2dfb..1de63ca 100644 --- a/my-blog/templates/index.html +++ b/my-blog/templates/index.html @@ -27,7 +27,7 @@
Read more {% if post.markdown_url %} - Markdown + .md {% endif %} {% if post.translation_url %} 🌐 diff --git a/my-blog/templates/post-complex.html b/my-blog/templates/post-complex.html index aa02383..90e3624 100644 --- a/my-blog/templates/post-complex.html +++ b/my-blog/templates/post-complex.html @@ -16,7 +16,7 @@
{% if post.markdown_url %} - πŸ“ Markdown + .md {% endif %} {% if post.translation_url %} diff --git a/my-blog/templates/post-simple.html b/my-blog/templates/post-simple.html index 2740b0d..b2f29c4 100644 --- a/my-blog/templates/post-simple.html +++ b/my-blog/templates/post-simple.html @@ -16,7 +16,7 @@
{% if post.markdown_url %} - πŸ“ Markdown + .md {% endif %} {% if post.translation_url %} diff --git a/my-blog/templates/post.html b/my-blog/templates/post.html index 71decac..dfa4943 100644 --- a/my-blog/templates/post.html +++ b/my-blog/templates/post.html @@ -16,7 +16,7 @@
{% if post.markdown_url %} - Markdown + .md {% endif %} {% if post.translation_url %}