Terrarium

いわゆる掃き溜めの ありふれた有象無象

SwiftでDropboxを利用するメモ

(注意:ほぼ自分用のメモです)

Dropboxを使う理由

現在自分用の簡単な消費管理アプリを作りたいと考えており,そのデータの保存先を色々検討していました. 次のような選択肢が考えられます.

  • AWSとかAzureとかのDBを利用
  • 自前のサーバのDBを利用
  • UserDefaultに格納
  • Google Spreadsheet
  • Dropbox

前者2つはコストがかかるので見送り,UserDefaultに全部しまってしまうのもアプリらしくない(?),Google SpreadsheetにはSwiftのライブラリがない(自分でAPIを叩く必要)などの理由から,今回はDropboxを利用してみることにしました.

SwiftyDropbox

DropboxをSwiftから使うためのライブラリです.

github.com

使い方は上のREADMEに書いてある通りになります.

インストールなど

行なった操作は次の通り.

  1. pod経由でインストール
  2. Dropboxのサイトでcreate app -> API_KEYの取得
  3. Info.plist編集その1 LSApplicationQueriesSchemes
  4. Info.plist編集その2 CFBundleURLTypes

ここでInfo.plistにdb-<APP_KEY>という形で値を指定するのですが,プロジェクトをGithubなどに公開したときにこれはAPP_KEYは漏れても大丈夫なのか?と感じました(自分は初心者なのでわからないのですが,多分SECRET_KEYの方が漏れなければ大丈夫なのかな,と考えてます,公開するときまでには調べなければ)

コーディング

基本的には次の3つを記述すれば動作します.

  1. AppDelegateのapplication(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool内で
DropboxClientsManager.setupWithAppKey("<APP_KEY>")

これでAPP_KEYを登録します.

  1. ボタンを押した時などのメソッド内で
DropboxClientsManager.authorizeFromController(UIApplication.shared,
                                                  controller: self,
                                                  openURL: { (url: URL) -> Void in
                                                    UIApplication.shared.openURL(url)
                                                  })

するとボタンを押すとログイン画面が出るようになります. ただこれだけだと最後のAllowを押してもブラウザが終了しません.

  1. AppDelegate内で
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    if let authResult = DropboxClientsManager.handleRedirectURL(url) {
        switch authResult {
        case .success:
            print("Success! User is logged into Dropbox.")
        case .cancel:
            print("Authorization flow was manually canceled by user!")
        case .error(_, let description):
            print("Error: \(description)")
        }
    }
    return true
}

を丸々追記. これで上記のログイン画面でAllowなどを押すと終了し,結果が返ってくるようになります.

  1. ファイルをアップロードするには,同様にボタンなどを押した時などのメソッド内で
if let client = DropboxClientsManager.authorizedClient {
    let fileData = "testing data example".data(using: String.Encoding.utf8, allowLossyConversion: false)!
    
    let request = client.files.upload(path: "/pocket_management/sample.txt", input: fileData)
        .response { response, error in
            if let response = response {
                print(response)
            } else if let error = error {
                print(error)
            }
        }
        .progress { progressData in
            print(progressData)
        }
} else {
    // error
    print("not logged in")
}

のようにやるのが良さそうです. clientの取得はControllerで1個用意しておくよりも毎回optional bindingで呼び出した方が良いのか…? (そのほうがエラー処理が書きやすそうに思える)

終わりに

本当にメモですが書いておきました. せっかくアプリを作るのでデザインからやったり色々試してみようと思います.

TrelloのUIを透明化するChrome拡張機能を作る

f:id:tellusium:20180709172959p:plain

はじめに

私はTrelloが好きで,タスク管理に使っているのですが,最近になって(ようやく)画面の背景に写真が(フリープランでも)使えることを知りました. 単色に飽きていたとこだったので,喜んで写真にしてみたところ,思ったよりパッとしないなという印象でした.

f:id:tellusium:20180708213630p:plain

これはまだ良いのですが,カードが多くなり

f:id:tellusium:20180708213840p:plain

のようになってしまうと,せっかくの綺麗な背景が台無しになってしまうわけです. そこで,カードを半透明にすれば良いのでは?と考え,chrome extensionで実装してみました.

Chrome Extension

Chrome extensionとは,

Extensions are small software programs that customize the browsing experience. They enable users to tailor Chrome functionality and behavior to individual needs or preferences. They are built on web technologies such as HTML, JavaScript, and CSS.

と公式ページに書かれています.すなわち,ユーザがChromeの機能を追加したりできるというものです.

What are extensions? - Google Chrome

Chrome extensionによって,Webサービスに機能を追加したりすることもできます. 様々なサイトにTogglのボタンを追加できるextensionや,Trelloにいくつか便利な機能を追加するUltimelloなどです.

chrome.google.com

chrome.google.com

これらはWebサイトのDOMを編集してボタンを追加し,それをトリガーに機能が書かれたJavascriptを実行することで実現されています.

すなわち,Chrome extensionを使うことでWebサイトの見た目やデザインを変更することもできるわけです. (Chrome extensionは非常に多くの機能を持つことができます.詳しくは公式ドキュメントなどをご覧ください)

Content script

今回は,Chrome extensionで使うことができる機能のうち,Content scriptというものを用います.

Content Scripts - Google Chrome

CSSをいじる方法はないかと探していたところ,下のページが見つかり,どうやらContent scriptを使っているようだということがわかりました.

marmooo.blogspot.com

公式ドキュメント曰く,

Content scripts are files that run in the context of web pages. By using the standard Document Object Model (DOM), they are able to read details of the web pages the browser visits, make changes to them and pass information to their parent extension.

すなわち,ブラウザが表示したWebページを読み込み,それらを変更したりできるらしいです.

詳細な作り方は公式チュートリアルなどを参考にしましたが,基本的にはフォルダを用意して,manifest.jsonというファイルに色々書き込みます. 変更したいスタイルについては,transparentize.cssに書き込みます. また,上で参照したブログにおいて!importantをつける必要があると書かれており,実際そうしないと反映されなかったため,全てに!importantをつけました(ここはもう少し賢くできるかもしれません).

https://developer.chrome.com/extensions/getstarted

// ディレクトリ構造
trello_transparentizer
├── manifest.json
└── transparentize.css

manifest.jsonです.matchesの部分に適用したいWebサイトのURLを記述します.今回はTrelloのボードのURLのはじめに付いている部分を指定しました.

{
    "name": "Trello Transparentizer",
    "version": "1.0",
    "description": "Transparentize trello interface.",
    "content_scripts": [
       {
        "matches": ["https://trello.com/b/*"],
        "css": ["transparentize.css"]
       }
    ],
    "manifest_version": 2
}

transparentize.cssです.Developer toolを使って変更したい要素のクラス名を探し,そのクラスのcssを上書きする形にしています.

/* リストの背景 */
.list {
    background-color: rgba(0, 0, 0, 0.5) !important;
}
/* カードの背景 */
.list-card {
    background-color: rgba(255, 255, 255, 0.7) !important;
    box-shadow: 0 0 0 #000 !important;
}
/* hover時のカードの背景 */
.list-card.active-card {
    background-color:  rgba(255, 255, 255, 0.9) !important;
}
/* リストの名前 */
h2.list-header-name-assist {
    color: white !important;
    font-weight: normal !important;
}
/* リストの名前(Ultimello使用時)*/
.list-header textarea {
    color: white !important;
    font-weight: normal !important;
}
/* カードをhoverした時に出てくる編集ボタン */
.expanded-list-card-operation {
    background-color: rgba(0, 0, 0, 0) !important;
}
/* スクロールバーの背景 */
.u-fancy-scrollbar::-webkit-scrollbar-track-piece {
    background: rgba(0, 0, 0, 0.3) !important;
}

以上を記述した後,その他のツール→拡張機能デベロッパーモードON→パッケージ化されていない拡張機能を読み込む→先ほどのフォルダを指定,という流れで拡張機能をインストールできます. 拡張機能を有効化した後にTrelloのボードを更新すると,次のように背景が透けて見えるようになります.

f:id:tellusium:20180709171418p:plain

以上でTrelloのUIを透明化し,背景の写真を映えさせることができるextensionが完成しました.

まとめ

カードが多すぎると背景の写真が全く見えなくなってしまうという問題を,UIを一部透明化するChrome extensionを作ることで解決しました. 今回は勉強も兼ねて新しくextensionを作りましたが,user style sheetを導入するという手法もあります. 指定したサイトに対し自分のCSSを適用できるという機能であり,これを可能にするいくつかのChrome extensionが公開されているようです.

今のところextensionとしてリリースはしない予定ですが(user style sheetの方が単純なため)一応Githubには公開しています.

github.com

スプラトゥーンのインクカラーをまとめてみた

スプラトゥーンというゲームでは,非常に鮮やかな様々な種類の「インク」が使われています. せっかくなので自分でもインクの色を使いたいと思い,可能な範囲で調べてみました.

注意:アプリに使われている色をとったため,実際に使われているものとは異なる可能性があります.参考にする場合は自己責任でお願いします.

f:id:tellusium:20180630215121p:plain#16D819
f:id:tellusium:20180630215226p:plain#440FC9
黄緑f:id:tellusium:20180630215233p:plain#CBF623
f:id:tellusium:20180630215240p:plain#A41FE3
f:id:tellusium:20180630215247p:plain#EF2E7F
f:id:tellusium:20180630215258p:plain#FECD01
f:id:tellusium:20180630215201p:plain#FF5602
ターコイズf:id:tellusium:20180630215540p:plain#04F2CD
水色f:id:tellusium:20180630215153p:plain#39DDEC

調査方法

実際にゲーム画面で行なったのではなく,イカリング2のアプリを参考にしました.

1. ステージ一覧から使われているインクを調べる

一通り目を通すと,緑,青,黄緑…と合計9種類見つかりました.

2. その色が使われているアプリの画面をスクショする

緑から黄色までは,自分のアカウントの詳細表示の場面からとりました. 編みかけの明るい方をとっています.おおよそ同じ色なので,これでいいかなと. 下がその画像です↓↓↓

f:id:tellusium:20180701140333j:plain

加えて,橙はサーモンランから,ターコイズはタコの塗りポイントチャレンジからとってきました.

f:id:tellusium:20180701140513p:plain f:id:tellusium:20180701140517p:plain

水色だけはどうしても使われているパーツが見当たらなかったので,ステージのインクの色からとっています. ただこれは光の当たり具合により場所によって色が変わってくるので,それっぽい部分から色をとりました.

f:id:tellusium:20180701140522p:plain

フェスの色

フェスの色については,画面で使われている色とアプリで使われている色がちょっと違うと感じたため,今の所はとっていません. 余力があったらそのうち追記するかもしれないです.

正規表現の最短マッチングにおける"?"についての瑣末な話

最短マッチ

私は正規表現について簡単な用途では使える気でいたのですが,あるとき次のような正規表現に出会いました.

.*?

.*は任意の文字が0個以上,というのはわかるのですが,そのあとの?がわからない. もちろんこの正体は,ご存知の方は多いでしょうが「最短マッチ」というものです.

私はこれに出会うのは初めてだったので,なるほど…と思ったのですが,これを見た時に色々考えてしまいました.

「?は0個か1個かを表す意味のメタ文字であるはず」

「ということは .* が0個か1個かを探しているのか?」

「いや,でもどう考えてもそれじゃ最短マッチにならない…」

結局考えると「?によって最短マッチとなるのは?の機能を活用したものなのか,それとも単に?に最短マッチとなる効果があるのか」という疑問にまとまり調査した結果,後者らしいということがわかりました.

Regex Tutorial - Repetition with Star and Plus曰く,「repititionオペレータはgreedyであるが,?をつけるとlazyにできる」とあったのでこれで結論みたいです. 他のサイトでもメタ文字一覧の?にも同じことが書かれていたりしました.

おまけ

?という0個か1個というrepititionにも?が使えるらしいので試して見ました.

regex-testdrive.com

文字列"ab"に対して

  • ab? -> abにマッチ
  • ab?? -> aにのみマッチ

ちゃんと動作しているようです.使い所あるのか…?