Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
8 changes: 8 additions & 0 deletions .agents/rules/frontend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
trigger: always_on
---

> **# Frontend Architecture: clipifront (React Native)**
> * **Primary UI Framework:** Prioritize **Tamagui** for core styling and performance-critical components. Leverage the Tamagui compiler to ensure minimal runtime overhead.
> * **Component Selection:** Use **Gluestack UI** (v2+) for complex, accessible UI patterns (Modals, Selects, Actionsheets) where ARIA compliance and modularity are required.
> * **Decision Logic:** Favor Tamagui for layout and high-frequency components; switch to Gluestack when pre-built complex behavior is needed to save development time. Avoid mixing both in the same atomic component to keep the bundle lean.
26 changes: 26 additions & 0 deletions .aidocs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Clipi FAQ

**Q: What is the main architecture?**
A: Central Server (Broker) architecture. Devices act as clients connecting to a shared Go API server.
That has run to be able to run on desktop and mobile

**Q: Where does the backend run?**
A: The backend runs on port 50050 (managed in `back/`).

**Q: How do I start the backend?**
A: Navigate to `back/` and run `go run main.go`.

**Q: How do I start the frontend?**
A: Navigate to `clipiFrontC/clipiFrontC` and run:
1. `dotnet build -f net9.0-windows10.0.19041.0` Builds Net Muai App
2. `dotnet run -f net9.0-windows10.0.19041.0` Run the builded app

**Q: How does the client identify itself?**
A: It identifies itself using its local IP address.

**Q: How are notes stored?**
A: Notes are stored in `notes.db` using SQLite3 (managed by Go backend in `back/utils/db.go`).

**Q: What is `clipiFront`?**
A: It's the modern Net Muai Hybrid Windows frontend.

20 changes: 20 additions & 0 deletions .aidocs/map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Clipi - Project Architecture

## Technology Stack
- **Backend:** Go (Golang) with SQLite3
- **Frontend (Mobile):** React Native with Tamagui and Gluestack UI
- **Dependency Management:** `uv` for Python (if applicable), `npm`/`yarn` for JS/TS, `go mod` for Go.

## Core Logic Flow
Clipi is a personal clipboard synchronization tool.
- **Backend:** Handles data persistence and API endpoints for fetching/storing notes.
- **Frontend:** Provides the user interface for interacting with synchronized clipboard content.

## Data Schema (SQLite)
- `notes.db`: Likely contains tables for clips/notes with content and timestamps.

## Directory Structure
- `back/`: Go backend source code.
- `clipiFrontC/clipiFrontC`: C# .Net Muai Brazor Hybrid mobile application.
- `utils/`: Shared utilities (likely Python based on research).
- `.aidocs/`: Internal documentation.
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Python
__pycache__/
*.py[cod]
*$py.class
.venv/
.python-version
.pytest_cache/
.coverage
htmlcov/
dist/
build/
*.egg-info/
.uv/

# Go
bin/
back/bin/

# Node / React Native (Project level)
node_modules/
npm-debug.log
yarn-error.log
.metro-health-check*

# OS / IDE
.DS_Store
Thumbs.db
.vscode/
.idea/
*.swp
*.swo

# Project Specific
notes.db
.env

.vs/
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
49 changes: 49 additions & 0 deletions Deprecatedd/back.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from flask import request
from markupsafe import escape
from flask import Flask
import sqlite3
from datetime import datetime

import Deprecatedd.db as db

app = Flask(__name__)

con = db.get_connection()
cur = db.get_cursor()

"""
Functions (Areea proper to stor e all the function)
"""

# Initialize the db table if it is not already initialized
cur.execute("CREATE TABLE IF NOT EXISTS notes(id, user, content, date)")


"""
Routes
"""
@app.route("/hello", methods=["GET", "POST"])
def hello():
#Receive the post with the content and the id
print("Received post from front")
if request.method == "POST":
content = request.form.get('content')
print(content)
id = request.form.get("id")
user = request.form.get("user")
date = datetime.now()

cur.execute("INSERT INTO notes VALUES(?, ?, ?, ?)", (id, user, content, date))
con.commit()
else:
content = request.form.get('content')
id = request.args.get("id")
#Return the ID for debugging
return f"Post {id} received"


if __name__ == '__main__':
app.run(debug=True, port=9132)
print("Started")

print("Stopped")
24 changes: 24 additions & 0 deletions Deprecatedd/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import sqlite3

# Maintain an open connection to notes.db
# check_same_thread=False ensures Flask can query DB across its threads
con = sqlite3.connect("notes.db", check_same_thread=False)

# Internal cursor
_cur = con.cursor()

# Initialize the db table if it is not already initialized
_cur.execute("CREATE TABLE IF NOT EXISTS notes(id, user, content, date)")
con.commit()

def get_cursor():
"""
Returns the cursor to be used by other scripts.
"""
return _cur

def get_connection():
"""
Returns the connection object if commits are needed elsewhere.
"""
return con
88 changes: 88 additions & 0 deletions Deprecatedd/front.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import requests
import secrets
import sqlite3
import socket

#Load the db
con = sqlite3.connect("notes.db", check_same_thread=False)

cur = con.cursor()

#Host Link


"""
Function
"""

#Get users local IP for note indentification
def getIP():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
#Use port 1 to send udp a dummy packet so it returns the ip
s.connect(('8.8.8.8', 1))
ip = s.getsockname()[0]
except Exception:
#Loopback in case unreachable
ip = '127.0.0.1'
finally:
s.close()
return ip
#To make a post for the other device

url = f'http://{getIP()}:9132/hello'

print(url)
def posting():
#Get the clipboard
content = input("tf is on ur clipboard dude 😭")

#Get users user, so u can actually take his notes type shi yk?
user = getIP()
#Get a random 6 digit ID to indetify each clipboard note
id = secrets.randbelow(900000) + 100000

#The post content, what's going w the post
postContent = {'id': id, 'user': user, 'content': content}

#Sending the actual post
sendPost = requests.post(url, postContent)

print(sendPost.text)

#Basically the frontend for now sadly
while True:
#Question the user what he wants to do
if (temp := input("What do you want to do (list, send)")) == "list":
#Get ip to indetify the user
user = getIP()

#Get notes and dates from the user to list them
content = cur.execute("SELECT content, date FROM notes WHERE user = ?", (user, ))
actualContent = content.fetchone()

#Parses the date
s = actualContent[1]

parsedDate = f"{s[11:16]} - {s[8:10]}/{s[5:7]}/{s[0:4]}"

#Tell them the note and date
if actualContent != None or "None":
print(f"Your clipboard are: {actualContent[0]}, {parsedDate}")

elif temp == "send": #If they want to send a note call the send function, that posts the note to the host
posting()
elif temp == "listId": #Take a note by list
#Get the note id
note_id = input("K little bru, whats the note id??")

#Take the note from the id on the db
content = cur.execute("SELECT content FROM notes WHERE id = ?", (note_id, ))
actualContent = content.fetchone()

#Return the note
if actualContent != None or "None":
print(f"Your clipboard are: {actualContent[0]}")



File renamed without changes.
51 changes: 51 additions & 0 deletions back/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module github.com/bulgadev/clipi/back

go 1.26.1

require (
github.com/gin-gonic/gin v1.12.0
golang.org/x/mobile v0.0.0-20260312152759-81488f6aeb60
modernc.org/sqlite v1.47.0
)

require (
github.com/bytedance/gopkg v0.1.3 // indirect
github.com/bytedance/sonic v1.15.0 // indirect
github.com/bytedance/sonic/loader v0.5.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.30.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.59.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.1 // indirect
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
golang.org/x/arch v0.22.0 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/mod v0.34.0 // indirect
golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect
golang.org/x/tools v0.43.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
modernc.org/libc v1.70.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
)
Loading