أنا مطور Android ولا أرغب في العمل اليدوي.

عندما استقرت في Skyeng ، كانت الشمس مشرقة أكثر إشراقًا ، ولم يكن العشب أكثر خضرة (كان ذلك في أوائل الربيع) ، وطلب مني قائد الفريق أن أكتب إلى Jira كم من الوقت الذي قضيته في الترميز ، وكم من الحديث والمراجعة. مرة واحدة على الأقل كل أسبوعين.


وقالوا "بناء على هذه البيانات ، نحاول أن نفهم ما إذا كان من الضروري تعديل التقديرات وما إذا كانت هناك مشاكل في الاتصال في الفريق". ولكن من لم يُقال مثل "بابايكا". .

نظرًا لأننا جميعًا عمال عن بعد ، فقد بدت الفكرة معقولة. وأصبح الأمر مثيرًا للاهتمام بالنسبة لي حيث ذهبت هذه الساعات الثماني: لقد كانت هنا ، ولكن لماذا بالضبط؟ ومع ذلك ، كان قطع الأشجار غير عادي. والكسل بشكل عام. ثم قررت البحث عن شيء من شأنه أن يستمر في العمل بالنسبة لي. وأثناء عملية البحث ، انطلقت قليلاً وكتبت البرنامج المساعد لـ IntelliJ IDEA.

ستجد أدناهمراجعة ذاتية للأدوات الجاهزة ودراجتي (مع المصدر).

أدرس الحلول التي يستخدمها الفريق


أول شيء فعلته هو معرفة زملائي الذين يستخدمون ما. الخيارات هي تقريبًا ما يلي:

1. Clockify - زر واحد لحكم كل شيء


هل تحتاج إلى وقت لترميز أو كتابة أرصفة؟ سيضيف المكون الإضافي زرًا (بكمن رمادي غير بارز إلى حد ما) في أي مكان تقريبًا.


لذلك يبدو في محرر مستندات Google


وعلى GitHub

يمكنك الإعجاب بـ Natrekannyi على لوحة القيادة ، أو يمكنك الاستيراد إلى طاولة وإسقاطها في Jira.


يتم توفير التكامل في Jira بشكل منفصل ، أيضًا عن طريق امتداد المتصفح.

ومع ذلك ، من الممكن تحميل جدول مع سجلات العمل التي تم الحصول عليها من Clockify إلى تقويم العمل الخاص بك. ولتتبع الوقت في وضع عدم الاتصال ، توجد تطبيقات سطح مكتب لنظام التشغيل windows و linux و mac. تطبيقات الجوال أيضًا. الوظيفة الرئيسية مجانية ، ولكن هناك العديد من خطط التعريفة مع الأشياء الجيدة مثل الخصوصية والتذكيرات والقوالب للمشاريع.

2. توغل ، توغل فقط


كل شيء متشابه ، ولكن المزيد من الأشياء الجيدة - على سبيل المثال ، في تطبيق سطح المكتب يمكنك تعيين تذكيرات لنفسك حول تسجيل الوقت ، وتشغيل وضع pomodoro ، حتى أن هناك فرصة لربط تطبيق معين بمشروع معين وإعداد التتبع التلقائي.


ولكن هناك فارق بسيط: في اليوم الأول من الاستخدام ذهلت من هذه النافذة والإشعارات مع التذكير. على الرغم من أن النظرية بدت باردة)

3. Toggl + Python script : عندما يكون الزر لم يعد كافيا


اختراع زميلي. بطريقة ما ، قرر تقليل إيماءات تصدير الجداول إلى Jira وتحويل تفريغ الضرائب في Toggl إلى برنامج نصي. يمكنك وضع كرون والتمتع بالحياة.

4. Wakatime - حيث نذهب ، لا حاجة إلى أزرار


يسجل كل شيء بنفسه. لذلك ، فإن أول شيء يجب تذكره عند توصيل ملحق المتصفح الخاص به هو القائمة السوداء.

بالإضافة إلى الإضافات ، فإنه يوفر العديد من عمليات التكامل وعددًا مناسبًا من المكونات الإضافية لمعظم IDE والمحررين الأكثر شيوعًا.


تتتبع الإضافات الخاصة بـ IDE الوقت المستغرق في فرع بوابة محدد وفي ملف محدد. على الشاشة ، قائمة تلك المتاحة مؤثرة للغاية. سيرينيك - "في الخطط" ، من أجل تنفيذها السريع ، يمكنك التصويت. بعض المكونات الإضافية في اشتراك مدفوع مقابل 9 دولارات في الشهر.

بالإضافة إلى ذلك ، على لوحة التحكم ، يمكنك معرفة مقدار الوقت الذي يتم إنفاقه كنسبة مئوية على كتابة التعليمات البرمجية بلغات مختلفة: إذا كنت تتذكر أن مشروع Android العادي يتضمن استخدام Kotlin و Java و Groovy و xml - فهذا أمر منطقي لنفسه). وإذا كنت تعمل مع المكون الإضافي المثبت لفترة من الوقت ، فستلاحظ أنه لا يرحم إلى حد ما: تحصل لوحة المعلومات على وقت القراءة النشطة وكتابة التعليمات البرمجية. والالتصاق لا يدخل إلى الشاشة بمظهر زجاجي. وغني عن القول ، أحد الهواة.

حسنًا ، كود المصدر لـ WakaTime مفتوح: يمكنك محاولة فهم كيفية عمله ...
, ? IDE JetBrains.

. WakaTime.java. , , Heartbeat (), WakaTime CLI . , , , .

كتابة دراجتك عن طريق القياس


ربما يكون مسدس البطاطا أكثر فائدة ، لكنك لن تفعل أي شيء لأغراض البحث. بعد التأمل في مصادر WakaTime ، قررت إنشاء مكون إضافي خاص بي يمكنه تتبع النشاط في IDE ، وتسجيل وقت الكتابة وإرساله إلى Jira (في تدفقنا ، تتم تسمية الفروع على اسم المهام في Jira ، لذلك تبدو واقعية تمامًا).

ولكي لا يملأ الخادم بالطلبات أثناء العمل على الرمز ، سنرسل السجلات عندما يتم إغلاق Android Studio ، وحتى تلك اللحظة يتم تخزينه محليًا.

1. ما هي الكيانات التي يمكن أن نجدها في شفرة المصدر للمكون الإضافي (ونستخدمها في منطقتنا)؟


نحن لا نستخدم مكونات (هذا هو الإرث ) ، التي كانت في السابق الوحدات الهيكلية الرئيسية للمكون الإضافي. قد يكون مستوى التطبيق أو مستوى المشروع أو مستوى الوحدة النمطية. يوجد ApplicationComponent في مصدر WakaTime ، لكنهم يستطيعون ، رمز المصدر عمره خمس سنوات ويجب أن يحافظ على التوافق مع الإصدارات السابقة. ترتبط المكونات بدورة حياة المستوى المرتبط بها. لذلك ، على سبيل المثال ، يتم تحميل ApplicationComponent عند بدء تشغيل IDE. عند استخدامها ، سيحظرون إعادة تشغيل المكون الإضافي دون إعادة تشغيل IDE ويتصرفون بشكل غير سار بشكل عام. لذلك ، من الأفضل استخدام الخدمات بدلاً من ذلك.

نحن نستخدم الخدمات- الوحدات الهيكلية الرئيسية الحالية. وهي مقسمة إلى نفس مستويات التطبيق والمشروع والوحدة ، وسوف تساعدنا على تغليف المنطق عند المستويات المناسبة وتخزين حالة المكون الإضافي.

على عكس المكونات ، يجب تحميل الخدمات من تلقاء نفسها باستخدام أسلوب ServiceManager.getService (). تضمن المنصة أن كل خدمة هي خدمة فردية.

إضافة إجراءات - يمكن أن تكون اختصارًا أو عنصرًا إضافيًا في القائمة - في كلمة واحدة ، فهي مسؤولة عن كل شيء يؤثر بطريقة أو بأخرى على إجراءات المستخدم في IDE.

نحن نستخدم الإضافات - أي امتداد للوظائف سيكون أكثر تعقيدًا من الإجراءات: على سبيل المثال ، اتصل بدورة حياة IDE وافعل شيئًا أثناء عرض شاشة البداية أو قبل الخروج.

يجب الإعلان عن كل هذا في الملف /META_INF/plugin.xml.

2. Plugin.xml و build.gradle



نافذة إنشاء المشروع. سنكتب البرنامج المساعد لدينا في Kotlin ، ونستخدم Gradle للتجميع.

هذا هو أول شيء نراه بعد إنشاء المكون الإضافي فارغًا في IDEA (ملف -> جديد -> مشروع ... -> Gradle -> IntelliJ Platform Plugin). يحتوي على معلومات حول تبعيات المكون الإضافي ووصفه المختصر. يجب أن يعلن عن مكونات المكونات الإضافية - المكونات والخدمات والإجراءات والتمديدات المذكورة سابقًا. لن تكون هناك نقطة دخول محددة - سيكون إجراء مخصص أو حدث دورة حياة IDE ، اعتمادًا على احتياجاتنا.

سنحتاج إلى هذه التبعيات - بعد كل شيء ، نريد كتابة مكون إضافي للاستوديو حتى يتمكن من العمل مع Git.

<depends>Git4Idea</depends>
<depends>com.intellij.modules.androidstudio</depends>

Git4Idea هو مكوّن إضافي لنظام الملفات الظاهري (VCS) ويوفر موضوعات يمكننا بفضلها الاستماع لاحقًا إلى أحداث git - مثل عمليات السحب على سبيل المثال.

نظرًا لأننا نريد أيضًا أن يكون المكون الإضافي قادرًا على العمل مع Jira ، فسنتصل من خلال gradle بمكتبة مقدمة بلطف مع عميل راحة. للقيام بذلك ، أضف مستودع مخزون Atlassian هناك:

repositories {
   mavenCentral()
   maven {
       url "https://packages.atlassian.com/maven/repository/public"
   }
}

وفي الواقع المكتبات:

implementation "joda-time:joda-time:2.10.4"
implementation("com.atlassian.jira:jira-rest-java-client-core:4.0.0") {
   exclude group: 'org.slf4j'
   dependencies {
       implementation "com.atlassian.fugue:fugue:2.6.1"
   }
}

هنا نحدد إصدار IDE الذي يهمنا والمسار إليه (أوه ، إذا بدأ Android Studio الحقيقي وعمل بنفس سرعة إصداره الخفيف لتصحيح المكونات الإضافية):

intellij {
   version '2019.1'
   plugins 'git4idea'
   alternativeIdePath 'E:\\Android Studio'
}

وهنا ، ربما ، في يوم من الأيام سنكتب عن وظيفة جديدة ومحسنة. لكن ليس الآن.

patchPluginXml {
   changeNotes """
     Add change notes here.<br>
     <em>most HTML tags may be used</em>"""
}

3. إنشاء واجهة مستخدم


لدفع شيء ما إلى Jira ، تحتاج أولاً إلى تسجيل الدخول. من المنطقي القيام بذلك مباشرة بعد فتح المشروع. يبدو أننا بحاجة إلى ملحق ، ولن نتردد في إعلانه في plugin.xml:

<postStartupActivity implementation="Heartbeat"/>

وإظهار الحوار فيه.

مكونات واجهة المستخدم هي بشكل أساسي مكونات من Swing مع بعض الامتدادات من platform sdk. كل هذا تم تغليفه مؤخرًا في kotlin ui dsl. في وقت كتابة هذا التقرير ، لاحظت الوثائق أن dsl يمكن أن يتغير كثيرًا بين الإصدارات الرئيسية ، لذلك نستخدمها بخوف طفيف:


override fun createCenterPanel(): JComponent? {

   title = "Jira credentials"
   setOKButtonText("Save")

   return panel {
       row {
           JLabel("Jira hostname")()
           hostname = JTextField("https://")
           hostname()
       }
       row {
           JLabel("Username:")()
           username = JTextField()
           username()
       }
       row {
           JLabel("Password:")()
           password = JPasswordField()
           password()
       }
   }
}

أنشأنا حوارًا ، وأظهرنا ذلك ، وتلقى أوراق اعتماد من Jira. الآن نحن بحاجة إلى حفظها ، ويفضل أن يكون ذلك بأمان ، قدر الإمكان. سيستمر PersisingStateComponent في الإنقاذ.

4. جهاز PersistingStateComponent (ليس معقدًا جدًا)


يمكن لـ PersistingStateComponent القيام بأمرين - saveState و loadState: إجراء تسلسل وحفظ الكائن الذي تم تمريره إليه واسترداده من التخزين.

حيث يجب عليه بالضبط حفظ البيانات ، يتعلم من شرح الدولة. يتم ذكر خيارين أبسط في الوثائق - حدد ملفك أو قم بتخزين كل شيء في إعدادات مساحة العمل:

@Storage("yourName.xml")
@Storage(StoragePathMacros.WORKSPACE_FILE) 
@State(
   name = "JiraSettings",
   storages = [
       Storage("trackerSettings.xml")
   ])

نظرًا لأن لدينا حالة خاصة ، ننتقل إلى الوثائق لتخزين البيانات الحساسة.

override fun getState(): Credentials? {
   if (credentials == null)  {
       val credentialAttributes = createCredentialAttributes()
       credentials = PasswordSafe.instance.get(credentialAttributes)
   }
   return credentials
}
override fun loadState(state: Credentials) {
   credentials = state
   val credentialAttributes = createCredentialAttributes()
   PasswordSafe.instance.set(credentialAttributes, credentials)
}

سوف يتعامل PersistingStateComponent آخر مع تخزين الوقت المسجل لفروع مختلفة.

اكتشف جيرا تسجيل الدخول. مع تخزين بيانات المستخدم أيضًا. الآن أنت بحاجة إلى تتبع حدث الخروج بطريقة أو بأخرى في الفرع لبدء العد التنازلي.

5. الاشتراك في الأحداث


توفر منصة IntelliJ فرصة لتعليق Observer على الأحداث التي تهمنا من خلال الاشتراك في موضوعاتهم في messageBus من المستوى المطلوب. هنا الرصيف ، إنه مثير للاهتمام.

الموضوع هو نقطة نهاية معينة ، تمثيل لحدث. كل ما عليك فعله هو الاشتراك وتنفيذ مستمع يجب أن يتعامل مع ما يحدث.

على سبيل المثال ، أحتاج إلى الاستماع إلى عمليات الدفع في Git ...

subscribeToProjectTopic(project, GitRepository.GIT_REPO_CHANGE) {
    GitRepositoryChangeListener {
        currentBranch = it.currentBranch
    }
}

... إغلاق التطبيق (لوقت البيدق لحسن الحظ) ...

subscribeToAppTopic(AppLifecycleListener.TOPIC) {
    object: AppLifecycleListener {
        override fun appWillBeClosed(isRestart: Boolean) {
            if (!isRestart) {
                JiraClient.logTime(entry.key, DateTime.now(), entry.value)
            }
        }
    }
}

... وحفظ المستندات (بحيث تكون كذلك).

subscribeToAppTopic(AppTopics.FILE_DOCUMENT_SYNC) {
    CustomSaveListener()
}

هذا ، من حيث المبدأ ، يكفي بالفعل (إذا لم يكن كذلك ، يمكنك دائمًا كتابة كتابك الخاص). ولكن ماذا لو أردنا سماع أدنى حركة التمرير والماوس؟

6. EditorEventMulticaster


إنه يجمع كل ما يحدث في نوافذ المحرر المفتوحة - التحرير ، وتغيير المنطقة المرئية ، وحركات الماوس - ويسمح لك بالاشتراك فيها في مكان واحد وعلى الفور.

الآن لدينا كل ما نحتاجه. يمكننا تحديد اسم المهمة في Jira من الفرع الحالي (إذا كان موجودًا) ، وحساب الوقت المستغرق في العمل عليها ، والخروج على الفور من الاستوديو لإضافتها إلى المهمة.

7. الرمز والتفاصيل هنا


للتشغيل ، تحتاج إلى أحدث إصدار من Android Studio (3.6.1).
لاختبار الأداء - git وفرع باسم مشابه عن بعد على الأقل للمهمة في Jira.
بحيث لا يخرج البرنامج الإضافي الوقت لوحدة التحكم فقط ، ولكنه يتتبعه - فك التعليق عن الخط المقابل في Heartbeat.kt.

8. روابط مفيدة



PS وماذا اخترت في النهاية؟


- اللعنة ، إنه نوع من الشر. وإذا لم أكتب الرمز؟ وإذا اخترت أنفي وحاولت بجد لفهم ما يحدث فيه؟ في القانون ، بمعنى. بعد كل شيء ، هذا يستغرق معظم الوقت.

- ثم قم بتمريره على الأقل.

- لذا فهي ليست بعيدة عن محاكاة النشاط العنيف. وبعد ذلك ، لا يمكنني إغلاق الاستوديو لأسابيع ولا يمكنني إعادة التشغيل. ربما لا نحتاج إلى مثل هذه السعادة؟

"بالتأكيد ليست ضرورية." ثم هناك حاجة لسبب آخر ، وإلا أحببت كتابة الإضافات. وما زلت لا أفهم حقا VCS.

"هل تستخدمه بنفسك؟"

- لا. تعلمت بطريقة أو بأخرى تسجيل الدخول بيدي ، بشكل غير محسوس لنفسي.

All Articles