hackatime/app/helpers/application_helper.rb
Mahad Kalam 922e7384c0
Fix email from name/dates, login flash, wakatime_setup redirect, Sunday 6:30pm GMT (#1067)
* Smol fixes

* Map <<LAST_LANGUAGE>

* whoops

* Fix

* Move emails from Friday to Sunday
2026-03-13 10:53:57 +00:00

218 lines
6.3 KiB
Ruby

module ApplicationHelper
def cache_stats
hits = Thread.current[:cache_hits] || 0
misses = Thread.current[:cache_misses] || 0
{ hits: hits, misses: misses }
end
def requests_per_second
rps = RequestCounter.per_second
rps == :high_load ? "lots of req/sec" : "#{rps} req/sec"
end
def global_requests_per_second
rps = RequestCounter.global_per_second
rps == :high_load ? "lots of req/sec" : "#{rps} req/sec (global)"
end
def current_theme
theme_name = current_user&.theme
return User::DEFAULT_THEME if theme_name.blank?
return theme_name if User.themes.key?(theme_name)
User::DEFAULT_THEME
end
def current_theme_color_scheme
User.theme_metadata(current_theme).fetch(:color_scheme, "dark")
end
def current_theme_color
User.theme_metadata(current_theme).fetch(:theme_color, "#c8394f")
end
def superadmin_tool(class_name = "", element = "div", **options, &block)
return unless current_user && (current_user.admin_level == "superadmin")
concat content_tag(element, class: "superadmin-tool #{class_name}", **options, &block)
end
def admin_tool(class_name = "", element = "div", **options, &block)
return unless current_user && (current_user.admin_level == "admin" || current_user.admin_level == "superadmin")
concat content_tag(element, class: "admin-tool #{class_name}", **options, &block)
end
def viewer_tool(class_name = "", element = "div", **options, &block)
return unless current_user && (current_user.admin_level == "viewer")
concat content_tag(element, class: "viewer-tool #{class_name}", **options, &block)
end
def dev_tool(class_name = "", element = "div", **options, &block)
return unless Rails.env.development?
concat content_tag(element, class: "dev-tool #{class_name}", **options, &block)
end
def country_to_emoji(country_code)
return "" unless country_code.present?
c = country_code.upcase.chars.map { |c| (0x1F1E6 + c.ord - "A".ord).to_s(16) }
t = c.join("-")
image_tag(
"https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/#{t}.svg",
alt: "#{country_code} flag",
class: "inline-block w-5 h-5 align-middle",
loading: "lazy"
)
end
# infer country from timezone
def timezone_to_country(timezone)
return null unless timezone.present?
tz = ActiveSupport::TimeZone[timezone]
return null unless tz && tz.tzinfo.respond_to?(:country_code)
tz.tzinfo.country_code || null
end
def timezone_difference_in_seconds(timezone1, timezone2)
return 0 if timezone1 == timezone2
tz1 = ActiveSupport::TimeZone[timezone1]
tz2 = ActiveSupport::TimeZone[timezone2]
tz1.utc_offset - tz2.utc_offset
end
def timezone_difference_in_words(timezone1, timezone2)
diff = timezone_difference_in_seconds(timezone1, timezone2)
msg = distance_of_time_in_words(0, diff)
if diff.zero?
"same timezone"
elsif diff.positive?
"It's currently #{Time.zone.now.in_time_zone(timezone1).strftime("%H:%M")} in #{timezone1} (#{msg} ahead of you)"
else
"It's currently #{Time.zone.now.in_time_zone(timezone1).strftime("%H:%M")} in #{timezone1} (#{msg} behind you)"
end
end
def visualize_git_url(url)
url.gsub("https://github.com/", "https://tkww0gcc0gkwwo4gc8kgs0sw.a.selfhosted.hackclub.com/")
end
def digital_time(time)
hours = time.to_i / 3600
minutes = (time.to_i % 3600) / 60
seconds = time.to_i % 60
[ hours, minutes, seconds ].map { |part| part.to_s.rjust(2, "0") }.join(":")
end
def short_time_simple(time)
hours = time.to_i / 3600
minutes = (time.to_i % 3600) / 60
return "0m" if hours.zero? && minutes.zero?
time_parts = []
time_parts << "#{hours}h" if hours.positive?
time_parts << "#{minutes}m" if minutes.positive?
time_parts.join(" ")
end
def short_time_detailed(time)
# ie. 5h 10m 10s
# ie. 10m 10s
# ie. 10m
hours = time.to_i / 3600
minutes = (time.to_i % 3600) / 60
seconds = time.to_i % 60
time_parts = []
time_parts << "#{hours}h" if hours.positive?
time_parts << "#{minutes}m" if minutes.positive?
time_parts << "#{seconds}s" if seconds.positive?
time_parts.join(" ")
end
def time_in_emoji(duration)
# ie. 15.hours => "🕒"
half_hours = duration.to_i / 1800
clocks = [
"🕛", "🕧",
"🕐", "🕜",
"🕑", "🕝",
"🕒", "🕞",
"🕓", "🕟",
"🕔", "🕠",
"🕕", "🕡",
"🕖", "🕢",
"🕗", "🕣",
"🕘", "🕤",
"🕙", "🕥",
"🕚", "🕦"
]
clocks[half_hours % clocks.length]
end
def human_interval_name(key, from: nil, to: nil)
if key.present? && Heartbeat.respond_to?(:humanize_range) && Heartbeat::RANGES.key?(key.to_sym)
Heartbeat.humanize_range(Heartbeat::RANGES[key.to_sym][:calculate].call)
elsif from.present? && to.present?
"#{from} to #{to}"
else
"All Time"
end
end
def display_editor_name(editor)
return "Unknown" if editor.blank?
case editor.downcase
when "vscode", "vs code" then "VS Code"
when "pycharm" then "PyCharm"
when "intellij", "intellijidea" then "IntelliJ IDEA"
when "webstorm" then "WebStorm"
when "phpstorm" then "PhpStorm"
when "datagrip" then "DataGrip"
when "ktexteditor" then "Kate"
when "android studio" then "Android Studio"
when "visual studio" then "Visual Studio"
when "sublime text" then "Sublime Text"
when "iterm2" then "iTerm2"
when "rubymine" then "RubyMine"
else editor.capitalize
end
end
def display_os_name(os)
return "Unknown" if os.blank?
case os.downcase
when "darwin" then "macOS"
when "macos" then "macOS"
when "wsl" then "WSL"
when "mozilla" then "Firefox"
else os.capitalize
end
end
def display_language_name(language)
LanguageUtils.display_name(language)
end
def language_color(language)
LanguageUtils.color(language)
end
def modal_open_button(modal_id, text, **options)
button_tag text, {
type: "button",
onclick: "document.getElementById('#{modal_id}')?.dispatchEvent(new CustomEvent('modal:open'))"
}.merge(options)
end
def safe_asset_path(asset_name, fallback: nil)
asset_path(asset_name)
rescue StandardError
fallback.present? ? asset_path(fallback) : asset_name
end
end