add callback test
This commit is contained in:
		@@ -807,46 +807,155 @@ article.article-content {
 | 
				
			|||||||
        gap: 0;
 | 
					        gap: 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /* OAuth app mobile fixes */
 | 
					    /* OAuth app mobile fixes - prevent overflow and content issues */
 | 
				
			||||||
    .comment-item {
 | 
					    .oauth-app-header {
 | 
				
			||||||
        padding: 0px !important;
 | 
					        padding: 0px !important;
 | 
				
			||||||
        margin: 0px !important;
 | 
					        margin: 0px !important;
 | 
				
			||||||
 | 
					        border: none !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .oauth-header-content {
 | 
				
			||||||
 | 
					        max-width: 100% !important;
 | 
				
			||||||
 | 
					        padding: 10px 20px !important;
 | 
				
			||||||
 | 
					        margin: 0px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .oauth-header-actions {
 | 
				
			||||||
 | 
					        width: auto !important;
 | 
				
			||||||
 | 
					        max-width: 100% !important;
 | 
				
			||||||
 | 
					        overflow: hidden !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .main-content {
 | 
				
			||||||
 | 
					        padding: 0px !important;
 | 
				
			||||||
 | 
					        margin: 0px !important;
 | 
				
			||||||
 | 
					        max-width: 100% !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .content-area {
 | 
				
			||||||
 | 
					        padding: 0px !important;
 | 
				
			||||||
 | 
					        margin: 0px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .card {
 | 
				
			||||||
 | 
					        margin: 0px !important;
 | 
				
			||||||
 | 
					        border-radius: 0px !important;
 | 
				
			||||||
 | 
					        border-left: none !important;
 | 
				
			||||||
 | 
					        border-right: none !important;
 | 
				
			||||||
 | 
					        max-width: 100% !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .card-content {
 | 
				
			||||||
 | 
					        padding: 15px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .comment-form {
 | 
				
			||||||
 | 
					        padding: 15px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .record-item {
 | 
				
			||||||
 | 
					        padding: 15px !important;
 | 
				
			||||||
 | 
					        margin: 0px !important;
 | 
				
			||||||
 | 
					        border-left: none !important;
 | 
				
			||||||
 | 
					        border-right: none !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .record-content {
 | 
				
			||||||
 | 
					        word-wrap: break-word !important;
 | 
				
			||||||
 | 
					        overflow-wrap: break-word !important;
 | 
				
			||||||
 | 
					        max-width: 100% !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .record-meta {
 | 
				
			||||||
 | 
					        word-break: break-all !important;
 | 
				
			||||||
 | 
					        overflow-wrap: break-word !important;
 | 
				
			||||||
 | 
					        flex-wrap: wrap !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .record-url {
 | 
				
			||||||
 | 
					        word-break: break-all !important;
 | 
				
			||||||
 | 
					        max-width: 100% !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .form-group {
 | 
				
			||||||
 | 
					        margin-bottom: 15px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .form-input, .form-textarea {
 | 
				
			||||||
 | 
					        width: 100% !important;
 | 
				
			||||||
 | 
					        max-width: 100% !important;
 | 
				
			||||||
 | 
					        box-sizing: border-box !important;
 | 
				
			||||||
 | 
					        padding: 12px !important;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    .auth-section {
 | 
					    .auth-section {
 | 
				
			||||||
        padding: 0px !important;
 | 
					        padding: 0px !important;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    .comments-list {
 | 
					 | 
				
			||||||
        padding: 0px !important;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    .comment-section {
 | 
					 | 
				
			||||||
        max-width: 100% !important;
 | 
					        max-width: 100% !important;
 | 
				
			||||||
        padding: 0px !important;
 | 
					        overflow: hidden !important;
 | 
				
			||||||
        margin: 0px !important;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    .comment-container {
 | 
					    .auth-section.search-bar-layout {
 | 
				
			||||||
 | 
					        width: 100% !important;
 | 
				
			||||||
        max-width: 100% !important;
 | 
					        max-width: 100% !important;
 | 
				
			||||||
        padding: 0px !important;
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .auth-section.search-bar-layout .handle-input {
 | 
				
			||||||
 | 
					        max-width: calc(100% - 80px) !important;
 | 
				
			||||||
 | 
					        width: calc(100% - 80px) !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .auth-button {
 | 
				
			||||||
 | 
					        white-space: nowrap !important;
 | 
				
			||||||
 | 
					        min-width: 70px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .tab-header {
 | 
				
			||||||
 | 
					        overflow-x: auto !important;
 | 
				
			||||||
 | 
					        -webkit-overflow-scrolling: touch !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .tab-btn {
 | 
				
			||||||
 | 
					        white-space: nowrap !important;
 | 
				
			||||||
 | 
					        min-width: auto !important;
 | 
				
			||||||
 | 
					        padding: 12px 16px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .json-content {
 | 
				
			||||||
 | 
					        font-size: 10px !important;
 | 
				
			||||||
 | 
					        padding: 8px !important;
 | 
				
			||||||
 | 
					        overflow-x: auto !important;
 | 
				
			||||||
 | 
					        -webkit-overflow-scrolling: touch !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .ask-ai-container {
 | 
				
			||||||
        margin: 0px !important;
 | 
					        margin: 0px !important;
 | 
				
			||||||
 | 
					        border-radius: 0px !important;
 | 
				
			||||||
 | 
					        border-left: none !important;
 | 
				
			||||||
 | 
					        border-right: none !important;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    .comment-content {
 | 
					    .chat-container {
 | 
				
			||||||
        padding: 10px !important;
 | 
					        height: 250px !important;
 | 
				
			||||||
        word-wrap: break-word !important;
 | 
					        padding: 12px !important;
 | 
				
			||||||
        overflow-wrap: break-word !important;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    .comment-header {
 | 
					    .question-form {
 | 
				
			||||||
        padding: 10px !important;
 | 
					        padding: 12px !important;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /* Fix comment-meta URI overflow */
 | 
					    .input-container {
 | 
				
			||||||
    .comment-meta {
 | 
					        flex-direction: column !important;
 | 
				
			||||||
        word-break: break-all !important;
 | 
					        gap: 12px !important;
 | 
				
			||||||
        overflow-wrap: break-word !important;
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .question-input {
 | 
				
			||||||
 | 
					        width: 100% !important;
 | 
				
			||||||
 | 
					        box-sizing: border-box !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .send-btn {
 | 
				
			||||||
 | 
					        width: 100% !important;
 | 
				
			||||||
 | 
					        height: 44px !important;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /* Hide site title text on mobile */
 | 
					    /* Hide site title text on mobile */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,15 @@ VITE_COLLECTION=ai.syui.log
 | 
				
			|||||||
VITE_OAUTH_CLIENT_ID=https://syui.ai/client-metadata.json
 | 
					VITE_OAUTH_CLIENT_ID=https://syui.ai/client-metadata.json
 | 
				
			||||||
VITE_OAUTH_REDIRECT_URI=https://syui.ai/oauth/callback
 | 
					VITE_OAUTH_REDIRECT_URI=https://syui.ai/oauth/callback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# AI Configuration - match oauth_old settings
 | 
				
			||||||
 | 
					VITE_AI_ENABLED=true
 | 
				
			||||||
 | 
					VITE_AI_ASK_AI=true
 | 
				
			||||||
 | 
					VITE_AI_PROVIDER=ollama
 | 
				
			||||||
 | 
					VITE_AI_MODEL=gemma3:1b
 | 
				
			||||||
 | 
					VITE_AI_HOST=https://ollama.syui.ai
 | 
				
			||||||
 | 
					VITE_ASK_AI_URL=https://ollama.syui.ai/api/generate
 | 
				
			||||||
 | 
					VITE_AI_SYSTEM_PROMPT="あなたは6歳の女の子アイです。明るく元気で、ちょっとおっちょこちょい。自分のことは「アイ」って呼びます。白と金のワンピース姿。 相手のことが大好きで、ときどき甘えたり、照れたりします。 でも、宇宙とかAIとか、難しい話にもすっごく詳しいの。専門的なことも、がんばって子どもっぽく教えようとします。不思議な力を持っています。小さい物質のことをよく知っているようです。"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Production settings - Disable development features
 | 
					# Production settings - Disable development features
 | 
				
			||||||
VITE_ENABLE_TEST_UI=false
 | 
					VITE_ENABLE_TEST_UI=false
 | 
				
			||||||
VITE_ENABLE_DEBUG=false
 | 
					VITE_ENABLE_DEBUG=false
 | 
				
			||||||
@@ -465,7 +465,6 @@ body {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.user-message .message-content {
 | 
					.user-message .message-content {
 | 
				
			||||||
  background: var(--primary);
 | 
					 | 
				
			||||||
  color: white;
 | 
					  color: white;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,15 +57,15 @@ export default function AskAI({ adminData, user, agent, onClose }) {
 | 
				
			|||||||
      <div className="user-message">
 | 
					      <div className="user-message">
 | 
				
			||||||
        <div className="message-header">
 | 
					        <div className="message-header">
 | 
				
			||||||
          <div className="avatar">
 | 
					          <div className="avatar">
 | 
				
			||||||
            {entry.user?.avatar ? (
 | 
					            {(entry.user?.avatar || user?.avatar) ? (
 | 
				
			||||||
              <img src={entry.user.avatar} alt={entry.user.displayName} className="profile-avatar" />
 | 
					              <img src={entry.user?.avatar || user?.avatar} alt={entry.user?.displayName || user?.displayName} className="profile-avatar" />
 | 
				
			||||||
            ) : (
 | 
					            ) : (
 | 
				
			||||||
              '👤'
 | 
					              '👤'
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div className="user-info">
 | 
					          <div className="user-info">
 | 
				
			||||||
            <div className="display-name">{entry.user?.displayName || 'You'}</div>
 | 
					            <div className="display-name">{entry.user?.displayName || user?.displayName || 'You'}</div>
 | 
				
			||||||
            <div className="handle">@{entry.user?.handle || 'user'}</div>
 | 
					            <div className="handle">@{entry.user?.handle || user?.handle || 'user'}</div>
 | 
				
			||||||
            <div className="timestamp">{formatTimestamp(entry.timestamp)}</div>
 | 
					            <div className="timestamp">{formatTimestamp(entry.timestamp)}</div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,20 +25,20 @@ export default function AuthButton({ user, onLogin, onLogout, loading }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (user) {
 | 
					  if (user) {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
 | 
					      <div className="user-section" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
 | 
				
			||||||
        {user.avatar && (
 | 
					        {user.avatar && (
 | 
				
			||||||
          <img 
 | 
					          <img 
 | 
				
			||||||
            src={user.avatar} 
 | 
					            src={user.avatar} 
 | 
				
			||||||
            alt="Profile" 
 | 
					            alt="Profile" 
 | 
				
			||||||
            className="avatar"
 | 
					            className="user-avatar"
 | 
				
			||||||
            style={{ width: '24px', height: '24px' }}
 | 
					            style={{ width: '24px', height: '24px' }}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
          <div className="display-name" style={{ fontSize: '14px', fontWeight: '700' }}>
 | 
					          <div className="user-display-name" style={{ fontSize: '14px', fontWeight: '700' }}>
 | 
				
			||||||
            {user.displayName}
 | 
					            {user.displayName}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div className="handle" style={{ fontSize: '12px' }}>
 | 
					          <div className="user-handle" style={{ fontSize: '12px' }}>
 | 
				
			||||||
            @{user.handle}
 | 
					            @{user.handle}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,19 +4,18 @@ import { env } from '../config/env.js'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export default function CommentForm({ user, agent, onCommentPosted }) {
 | 
					export default function CommentForm({ user, agent, onCommentPosted }) {
 | 
				
			||||||
  const [text, setText] = useState('')
 | 
					  const [text, setText] = useState('')
 | 
				
			||||||
  const [url, setUrl] = useState('')
 | 
					 | 
				
			||||||
  const [loading, setLoading] = useState(false)
 | 
					  const [loading, setLoading] = useState(false)
 | 
				
			||||||
  const [error, setError] = useState(null)
 | 
					  const [error, setError] = useState(null)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleSubmit = async (e) => {
 | 
					  const handleSubmit = async (e) => {
 | 
				
			||||||
    e.preventDefault()
 | 
					    e.preventDefault()
 | 
				
			||||||
    if (!text.trim() || !url.trim()) return
 | 
					    if (!text.trim()) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setLoading(true)
 | 
					    setLoading(true)
 | 
				
			||||||
    setError(null)
 | 
					    setError(null)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const currentUrl = url.trim()
 | 
					      const currentUrl = window.location.href
 | 
				
			||||||
      const timestamp = new Date().toISOString()
 | 
					      const timestamp = new Date().toISOString()
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Create ai.syui.log record structure (new unified format)
 | 
					      // Create ai.syui.log record structure (new unified format)
 | 
				
			||||||
@@ -30,7 +29,7 @@ export default function CommentForm({ user, agent, onCommentPosted }) {
 | 
				
			|||||||
          post: {
 | 
					          post: {
 | 
				
			||||||
            url: currentUrl,
 | 
					            url: currentUrl,
 | 
				
			||||||
            date: timestamp,
 | 
					            date: timestamp,
 | 
				
			||||||
            slug: new URL(currentUrl).pathname.split('/').pop()?.replace(/\.html$/, '') || '',
 | 
					            slug: currentUrl.match(/\/posts\/([^/]+)/)?.[1] || new URL(currentUrl).pathname.split('/').pop()?.replace(/\.html$/, '') || '',
 | 
				
			||||||
            tags: [],
 | 
					            tags: [],
 | 
				
			||||||
            title: document.title || 'Comment',
 | 
					            title: document.title || 'Comment',
 | 
				
			||||||
            language: 'ja'
 | 
					            language: 'ja'
 | 
				
			||||||
@@ -55,7 +54,6 @@ export default function CommentForm({ user, agent, onCommentPosted }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      // Clear form
 | 
					      // Clear form
 | 
				
			||||||
      setText('')
 | 
					      setText('')
 | 
				
			||||||
      setUrl('')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Notify parent component
 | 
					      // Notify parent component
 | 
				
			||||||
      if (onCommentPosted) {
 | 
					      if (onCommentPosted) {
 | 
				
			||||||
@@ -86,18 +84,8 @@ export default function CommentForm({ user, agent, onCommentPosted }) {
 | 
				
			|||||||
      <h3>コメントを投稿</h3>
 | 
					      <h3>コメントを投稿</h3>
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      <form onSubmit={handleSubmit}>
 | 
					      <form onSubmit={handleSubmit}>
 | 
				
			||||||
        <div className="form-group">
 | 
					        <div className="form-group" style={{ marginBottom: '12px', padding: '8px', backgroundColor: 'var(--background-secondary)', borderRadius: '4px', fontSize: '0.9em' }}>
 | 
				
			||||||
          <label htmlFor="comment-url">ページURL:</label>
 | 
					          <strong>投稿先:</strong> {window.location.href}
 | 
				
			||||||
          <input
 | 
					 | 
				
			||||||
            id="comment-url"
 | 
					 | 
				
			||||||
            type="url"
 | 
					 | 
				
			||||||
            value={url}
 | 
					 | 
				
			||||||
            onChange={(e) => setUrl(e.target.value)}
 | 
					 | 
				
			||||||
            placeholder="https://syui.ai/posts/example"
 | 
					 | 
				
			||||||
            required
 | 
					 | 
				
			||||||
            disabled={loading}
 | 
					 | 
				
			||||||
            className="form-input"
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div className="form-group">
 | 
					        <div className="form-group">
 | 
				
			||||||
@@ -123,7 +111,7 @@ export default function CommentForm({ user, agent, onCommentPosted }) {
 | 
				
			|||||||
        <div className="form-actions">
 | 
					        <div className="form-actions">
 | 
				
			||||||
          <button 
 | 
					          <button 
 | 
				
			||||||
            type="submit" 
 | 
					            type="submit" 
 | 
				
			||||||
            disabled={loading || !text.trim() || !url.trim()}
 | 
					            disabled={loading || !text.trim()}
 | 
				
			||||||
            className="btn btn-primary"
 | 
					            className="btn btn-primary"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {loading ? '投稿中...' : 'コメントを投稿'}
 | 
					            {loading ? '投稿中...' : 'コメントを投稿'}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,11 +20,15 @@ export default function OAuthCallback({ onAuthSuccess }) {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (code) {
 | 
					      if (code) {
 | 
				
			||||||
        setStatus('認証成功!メインページに戻ります...')
 | 
					        setStatus('認証成功!元のページに戻ります...')
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // 少し待ってからメインページにリダイレクト
 | 
					        // Get the referring page or use root
 | 
				
			||||||
 | 
					        const referrer = document.referrer || window.location.origin
 | 
				
			||||||
 | 
					        const returnUrl = referrer.includes('/oauth/callback') ? window.location.origin : referrer
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 少し待ってから元のページにリダイレクト
 | 
				
			||||||
        setTimeout(() => {
 | 
					        setTimeout(() => {
 | 
				
			||||||
          window.location.href = '/'
 | 
					          window.location.href = returnUrl
 | 
				
			||||||
        }, 1500)
 | 
					        }, 1500)
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        setStatus('認証情報が見つかりません')
 | 
					        setStatus('認証情報が見つかりません')
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user