volatile-static / Chartero

Chart in Zotero
https://gitee.com/const_volatile/chartero
Apache License 2.0
395 stars 8 forks source link

历史记录功能,或者,自定义列? #113

Closed Geo123abc closed 5 months ago

Geo123abc commented 5 months ago

历史记录功能,或者,自定义列?

模仿浏览器的 history 或者新建列,做一个更好的 open recent

方案甲,类似 chartero 的 library overview 界面:

  1. 打开PDF 的时候,查询历史记录中是否有这个条目,

    1. 如果没有,追加itemkey、打开时间到json中
    2. 如果有,更新当前时间到这个记录的打开时间
    3. 这个json中至少有itemkey、打开时间这两项,如果可以的话,结合已有功能,把总计的阅读时长也加进来(?)
  2. 允许自定义历史记录的条数
  3. 点击open recent,打开一个类似 谷歌浏览器history 的 tab 界面

    1. 对于每一个条目,左边是一个多选框,中间是作者、年、标题(这个可以是一栏,或者多栏),右边是这篇文章的阅读时长
    2. 多选框允许勾选个别记录,然后删除这些记录
    3. 有类似浏览器时间分组之类的显示效果

方案乙,自定义一个新的列到zotero主界面:

类似 zotero 条目自有的 Date Added、Modified可以排序,但是这两个参数是条目信息添加、更改的时间,而不是打开条目的时间,但是模仿这个功能,我们可以尝试着改造zotero的列:

  1. 使用zotero添加新列的API,插件提供添加新列的功能,比如添加一列“上次打开时间”,这个自定义列有两种方案:

    1. 方案A:一个真实的新列(不知道是否可行)
    2. 方案B:一个类似zotero style 的 remark列、titleTranslation:列、abstractTranslation:列的方案(推荐这种方案,即使以后离开zotero到其它软件,也方便,滑稽.jpg):

      1. 把信息存储在extra字段,形式是xxxx:内容
      2. zotero的主界面也能按照remark列进行排序等操作。应该是插件读取extra字段的remark:内容,然后进行显示,只要设置好“新建列名”和“extra字段的xxxx:”的对应关系即可渲染;
      3. 这种方案可能复杂一些,但是灵活性、扩展性更高,比如添加各种新的列星标上次打开时间被引次数......
      4. 技术参考:

        1. dev:zotero_7_for_developers - Custom Item Tree Columns
        2. [Share] Auto-Translate the New Item's Title · windingwind/zotero-actions-tags · Discussion #107Zotero.PDFTranslate.data.ztoolkit.ExtraField.setExtraField(item, "abstractTranslation", abstractResult);
      5. !!!鉴于这个功能是修改zotero数据库的,需要测试好再发布,避免造成不可挽回的损失;
  2. 当打开条目时,添加当前时间到列“上次打开时间”,方案有两种:

    1. 插件自己添加或者修改时间到列“上次打开时间”
    2. zotero-actions-tags 脚本添加或者修改时间到列上次打开时间

      1. 如果新建列选择方案B,此处可以参考 extra字段处理 进一步做些增、改、删、查的脚本,便于用户维护

推荐方案乙的方案B,原因:

  1. 方案乙的扩展性高,代码量应该也属于比较小的;
  2. 方案乙结合 zotero 的 collection 切换功能(在My library、各个 collection 切换)、按照列排序等,这些操作对用户更熟悉、更方便;
  3. 和zotero-actions-tags 脚本联合,实现1+1>2
  4. 如果新建一个列,并把数据直接存储在这个列上,我感觉没有现在remark: 、abstractTranslation:、titleTranslation: 这种方式优雅:这三种都是把数据存储在extra字段,并不在自定义列中直接存储数据。如果日后用户换用文献管理软件,这会友好一些。

具体需要的插件功能

举一个具体的例子

  1. 插件新建一个zotero的列,名字是usermark,属性是展示列,然后指定这一列关联extra下面的abstractTranslation:usermark这一列就会显示extra下面的abstractTranslation:对应的内容,两种修改方案;

    1. 通过直接修改extra中对应的内容修改列;
    2. 类似style插件的remark功能,既可以通过直接修改extra中对应的内容修改列,也可以通过修改右侧条目信息栏的usermark字段进行修改。这种需要自定义列在条目信息栏中也占据一个位置,可能会导致信息栏太长了。
  2. 插件新建一个zotero的列,名字是userclass,属性是实体列,这种列是直接存储内容的,不太推荐使用这种;这种必须需要自定义列在条目信息栏中也占据一个位置,提供修改的入口,会导致信息栏太长。
  3. 列的删除、修改功能。删除自定义列时,展示列比较简单,不会对条目产生实质改变,但是删除自定义实体列会删除这一列中的内容,需要谨慎。

综上,按照简单原则,只添加展示列功能即可,用户通过手动直接修改extra中对应的内容修改列。

应用场景:

  1. 星标
  2. 上次打开时间
  3. “Journal Abbr”是针对参考文献的,userJournalAbbr可以定义更多的、用户理解的期刊缩写,减少对zotero主面板的空间占用。比如美国国家科学院院刊 ,全称Proceedings of the National Academy of Sciences of the United States of America,“Journal Abbr”一般记为Proc. Natl. Acad. Sci.,但是我们人的记忆一般称为PNAS
  4. 其它暂时想不到各种场景......
volatile-static commented 5 months ago

首先非常感谢你提出如此详实的建议与方案!

Geo123abc commented 5 months ago

感谢回复,

展示列实体列这两个概念是我自定义的,如你所说,我对Zotero提供的API不太了解,我只是有一个大概的框架。

  1. 展示列就是类似zotero style 的 remark列、zotero translate 的titleTranslation列、abstractTranslation列,他们的数据是存储在extra字段下面的一个关键词中,如果渲染到zotero主界面中,需要插件从extra字段中分离出相关内容;
  2. 实体列是类似 zotero 信息面板中的DOIURL等原生字段的列,这些列和extra字段完全无关;

对于使用乙B方案添加新列的功能我很期待,我目前能想到的是可能需要注意这几个参数:

  1. 键值:这个是面向zotero软件的,可能需要理解Zotero提供的API。这个也是我大致的理解,如有困惑,请忽略。
  2. 显示的列名称:面向用户的,就是在主界面显示的列名称。
  3. 显示的内容来源:对应extra字段下面的子字段,比如remarktitleTranslationabstractTranslation,不能有空格。

至于和其他插件的联动,等乙B做出来之后,我试一下我的方案是否可行,如果可行,到时候我再分享出来。

期待!

volatile-static commented 5 months ago
Geo123abc commented 5 months ago

新建列是用户自己触发的,当新建列的时候,需要用户自己填入一组相关信息,初步是下面三个参数:

  1. 键值:这个可以是插件自己生成的随机码;
  2. 显示的列名称:面向用户的,就是在主界面显示的列名称,这个应该是用户手动填入的,所以不会涉及到多语言问题。
  3. 显示的内容来源,比如

    1. 填入extra-titleTranslation,那么这一列就是显示extra字段下titleTranslation:对应的内容;
    2. 如果填入zotero自有的字段,比如,titleyearlanguagefirstCreator等。(当然这种情况一般是没有意义的,但是今天看到了这个内容,所以也许对有些用户是有用的)

      至于算法实现,那就是我的盲区了,可能可以从 zotero translate 源代码中查找titleTranslation列、abstractTranslation列的实现方法,照猫画虎。

Geo123abc commented 5 months ago

使用 zotero-actions-tags 解决,参考如下:

Event: Main Window Load Operation: Script

const registeredDataKey = await Zotero.ItemTreeManager.registerColumns({
    dataKey: 'openedTime',
    label: 'Opened Time',
    pluginID: 'zoterotag@euclpts.com',
    dataProvider: (item, dataKey) => {
        return Zotero.PDFTranslate.data.ztoolkit.ExtraField.getExtraField(item, 'titleTranslation');
    },
});

重启zotero生效

感谢 @volatile-static