V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  hamsterbase  ›  全部回复第 5 页 / 共 17 页
回复总数  338
1  2  3  4  5  6  7  8  9  10 ... 17  
@zaiziw

感谢反馈,下个版本会兼容。

issue 可直接在 hamsterbase 主仓库提。
308 天前
回复了 jzjjzj 创建的主题 旅行 steam deck 实际用起来如何? 有老铁分享下吗?
优点
1. 手感不错
2. 支持随时暂停。


缺点
1. 部分游戏不兼容
2. 太大了,不适合日常带出门
3. 分辨率略低
setpp +1
在搜索框按方向键 上、下 。 可以切换不同的关键字。

我试了一下,滚动条的记录还在。

1 楼说的 New Search Editor 也可以, 可以把搜索保存为 code-search 文件
@dofine 最简单的应该是 render.com

分别绑定前端和后端的开源仓库。 点击部署就行了。

目前前端还没做切换后端地址的功能,可能要改一行代码,把后端域名换了。
@aks 不会的。 本地一直有全部数据。
321 天前
回复了 tntin 创建的主题 分享创造 [调研]关于笔记工具 你有什么要求?
@0o0O0o0O0o

我刚好开发了两个产品,分别满足部分需求

第一个是偏剪藏。 用来收集所有外部的只是

hamsterbase ,非开源,自部署,点对点同步,提供浏览器差价。实现网页的阅读,储存,批注,搜索。

第二个偏快速记录。用来收集自己的想法

memotalk. 基于 pwa 开发,启动速度快,离线可用,跨全部平台。 本地优先,服务端和客户端都开源,端到端加密。

欢迎来提交 pr 支持 s3 。
@metalvest 手机浏览器里安装到桌面。 就可以断网使用了。

## 安装 PWA
在 Android 设备上,打开 Chrome 应用 Chrome 。
转到包含要安装的 PWA 的网站。
点按安装。
按照屏幕上的说明操作。
https://zhuanlan.zhihu.com/p/87424183

推荐读一下这篇文章。 讲 vs code 和 Basecamp 是怎么保障发布的。

下面是我拷贝过来的原文



直到最近我读了 Basecamp 的产品方法论 Shape Up: Stop Running in Circles and Ship Work that Matters 。这份文档介绍了 Basecamp 是如何保证,一个想法通过层层把关,在一个自由的工作环境中,最终准时变成产品发布出去的。

## 发布
重要的事情最先说,整个文档的核心目标就是发布。这些年大环境的熏陶下,大家都明白了 “Ship it”,重要的是把产品发布出来,因为一个产品没有问世见到客户,一切都是空谈。“Ship it” 很难,努努力总是可以达到的,没达到的团队就死了。

相比之下,更难的则是产品发布后,持续的发布迭代。为了确保每个 release 计划的新功能都能够发布出去,Basecamp 的第一个准则就是小步快跑,六个礼拜一个 release ,把 deadline 作为严格标准,其他事情都得为 deadline 做让步。
六个礼拜的时间是 Basecamp 实践后找到的最合适他们的产品发布周期。VS Code 也差不多,通常一个 release 持续四个礼拜或者五个礼拜。
我深有体会。 分享一下我的做法。


1. 先写好需求文档, 写完需求文档以后。
2. 严格按照需求文档开发,只能修 bug ,砍需求 。 不能加需求
3. 实现好一会自己测试一下, 把 bug 记录
4. 把 bug 都需求,不要加需求。
12. 经过 2 天 6 小时的开发。 一个本地优先的极简卡片笔记就开发完了。(只有最核心功能)

可以访问 https://memo-talk-web.onrender.com 体验

注意: 项目还没正式发布,只能拿来玩。,不要在这里储存任何数据。

1. 纯 web 实现, 压缩后不到 173 k 。
2. 支持离线编辑,再次联网后自动同步。
3. 两台设备输入相同的账户密码。 刷新页面刷新后,他们会自动同步到同一个状态。
4. 所有数据在本地加密,服务器不储存明文数据。
11. 服务器问题修复后,开始对接。 核心的云同步逻辑非常简单


const sdk = new FileAPISDK(url);

// 生成加密密钥
// userToken 用来标记用户身份,也是服务器文件夹的名字
// encryptionKey 是文件加密密码,encryptionKey 不会发送到服务
const { userToken, encryptionKey } = generateKeys(username, passowrd);

// 获取服务器数据库列表
const files: string[] = await sdk.getList(userToken);

const mergedFiles: string[] = [];

// 把服务器上的文件和本地合并,合并后加入等待删除列表
for (const file of files) {
try {
const remoteData = await sdk.getFile(userToken, file);
const database = decryptData(remoteData, encryptionKey);
memoTalkCore.merge(database);
mergedFiles.push(file);
} catch (error) {
console.log(error);
}
}

// 获取本地最新数据,加密
const currentData = encryptData(memoTalkCore.encode(), encryptionKey);
const fileName = sha256(currentData);

// 把加密后的文档存到服务器
await sdk.createFile(userToken, fileName, currentData);

// 因为数据已经合并到本地了,所以把服务器的删掉
for (const mergedFile of mergedFiles) {
try {
await sdk.deleteFile(userToken, mergedFile);
} catch (error) {
console.log(error);
}
}
}
14. 发现服务器忘记配置跨域了。

q:koajs 如何开启跨区请求。
```
class FileAPISDK {
constructor(baseUrl = "http://localhost:9999") {
this.baseUrl = baseUrl;
}

async getList(folder) {
const response = await fetch(`${this.baseUrl}/public/api/v1/folder`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ folder }),
});

this._handleErrors(response);
return await response.json();
}

async getFile(folder, file) {
const response = await fetch(`${this.baseUrl}/public/api/v1/file`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ folder, file }),
});

this._handleErrors(response);
return await response.text();
}

async deleteFile(folder, file) {
const response = await fetch(`${this.baseUrl}/public/api/v1/file`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ folder, file }),
});

this._handleErrors(response);
return await response.text();
}

async createFile(folder, file, content) {
const response = await fetch(`${this.baseUrl}/public/api/v1/file`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ folder, file, content }),
});

this._handleErrors(response);
return await response.text();
}

_handleErrors(response) {
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
}
}
```
13: POE 一天一次的 gpt4 体验卡

帮我基于下面的代码,写一个 js sdk 出来。


https://github.com/hamsterbase/memo-talk/blob/main/server/index.ts
12:帮我写一个 sha256 的函数。 基于 ts . crypto-js. 输入字符串,输出 hex
11: 帮上面的 encryptedData ,decryptedData 写测试。 随机的 key 和 data 。 加密和解密后数据不变
10. 帮我编写一个 aes 加密函数. 输入 key 和 data, 返回加密后的数据. 输入 data 和 key , 返回解密后的数据

基于 crypto-js 和 ts
9 。 开始编写服务器需要的一些工具函数


Q:
帮我用 crypto-js 编写函数。

输入账户,密码。 生成两个 key

第一个 key sha256(memo:sha256(username):sha256(password):talk);
第二 key 。sha256(memo:password:talk

用 ts 编写

第一个 key 名字为 userToken , 第二个 key 名字为 加密密钥(用英文)
8. 简单更新了一下首页的 UI , 然后把储存从 localstorage 换到了 IndexedDB
开始真正对接服务器了。

第一版做的简单一点,在页面加载的时候异步合并一下服务器的数据,合并后把数据上传到服务器。
1  2  3  4  5  6  7  8  9  10 ... 17  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4802 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 24ms · UTC 09:58 · PVG 17:58 · LAX 02:58 · JFK 05:58
Developed with CodeLauncher
♥ Do have faith in what you're doing.