Skip to content

공유 추상화 계약

이 장에서는 Lertaro.PluginSdk 전체에서 공통으로 사용되는 핵심 데이터 모델, 읽기 전용 계약 및 스키마 기반 설정 추상화를 정리합니다.

1. 검색 결과 모델 ISearchResult

Lertaro 아키텍처에서 플러그인은 검색 결과에 대해 항상 읽기 전용 인터페이스 ISearchResult를 통해 접근합니다.

csharp
namespace Lertaro.PluginSdk;

public interface ISearchResult
{
    string Name { get; }                  // 표시 이름 (예: "Lertaro.exe")
    string FullPath { get; }              // 절대 물리 경로 (예: "C:\Program Files\Lertaro\Lertaro.exe")
    string ContextDirectory { get; }      // 부모 디렉토리 경로 (예: "C:\Program Files\Lertaro")
    bool IsDir { get; }                   // 디렉토리 여부
    bool IsApplication { get; }           // 실행 파일 또는 바로가기 여부
    FileMetadata Metadata { get; }        // 고성능 파일 메타데이터 (크기, 수정일 등)
    bool[]? GetHighlightMask(string text, string query); // 문자 단위 하이라이트 마스크 계산
}

NOTE

ISearchResult.Metadata는 인메모리 USN/MFT 인덱스에서 직접 주입되므로 이 속성에 접근할 때 디스크 I/O나 IPC 호출이 전혀 발생하지 않습니다. 결과 세트에 포함되지 않은 외부 경로를 조회할 때만 FileMetadataService.GetMetadataAsync를 호출하세요.

2. 파일 메타데이터 구조체 FileMetadata

csharp
public readonly record struct FileMetadata(
    long Size,
    DateTime Created,
    DateTime Modified,
    DateTime Accessed
);
  • 타임스탬프는 모두 **로컬 시간 (Local Time)**입니다.
  • Metadata == default인 경우(필드가 0 또는 DateTime.MinValue) 물리 인덱스가 아닌 플러그인이 동적으로 생성한 결과임을 나타냅니다.
  • Metadata.Modified != default로 메타데이터 미제공 상태와 실제 존재하는 0바이트 파일을 정확히 구분할 수 있습니다.

3. 호스트 윈도우 제어 인터페이스 IPluginSearchWindow

액션 실행 콜백(ISearchResultAction.Execute 등)이 호출될 때 호스트 윈도우 작업을 안전하게 트리거하기 위해 전달됩니다:

csharp
public interface IPluginSearchWindow
{
    void LocateInExplorerExternal(string path);       // 탐색기 등에서 파일 위치 강조 표시
    void OpenFileOrFolderExternal(string path);       // 기본 앱으로 일반 실행
    void OpenFileOrFolderAsAdminExternal(string path);// 관리자 권한으로 실행
    void HideWindow();                                // 현재 검색창 숨기기
}

4. 스키마 기반 설정 시스템 IConfigurable

플러그인에서 사용자 설정 항목을 제공해야 하는 경우 IConfigurable을 구현하면 XAML 작성 없이도 설정 → 플러그인 → 구성에 네이티브 폼 UI가 자동 렌더링됩니다:

csharp
public interface IConfigurable
{
    PluginConfigSchema GetConfigSchema();
}

지원 필드 타입 ConfigFieldType

필드 타입컨트롤 및 동작 설명
Boolean토글 스위치 또는 체크박스.
Text텍스트 입력 상자. RequireNonEmpty 활성화 시 빈 문자열일 때 DefaultValue로 자동 폴백.
텍스트 선택SelectionStartSelectionLengthText 필드 입력 대화상자의 0부터 시작하는 초기 선택 범위를 지정합니다.
Integer최솟값과 최댓값을 지정할 수 있는 숫자 조절 상자.
ChoiceChoices 또는 ChoiceOptions 목록에서 선택하는 드롭다운.
Hotkey키 녹화 컨트롤(RequireModifier = true로 수식키 필수화 가능).
FilePath / FolderPath찾아보기 대화상자 버튼이 포함된 경로 입력 컨트롤.
StringList항목 추가, 삭제, 순서 변경 및 자동 줄바꿈을 지원하는 여러 줄 목록 상자이며, 실제 줄바꿈은 시각적 표시로만 나타나고 설정 값에는 포함되지 않습니다.
Group접을 수 있는 카드 형태의 하위 필드 그룹(SubFields).
CustomControl커스텀 WPF UIElement 컨트롤을 직접 임베드.
Button작업 버튼을 표시하고 필드의 OnClick 델리게이트를 호출하며 설정 값은 저장하지 않습니다.

아이콘 필드

스키마 키가 Icon인 텍스트 필드에는 아이콘 미리보기가 표시됩니다. WPF Path Data를 직접 입력할 수 있으며, 전체 SVG/XML 문서를 붙여 넣으면 호스트가 모든 <path d> 값을 추출해 결합하고 변환된 WPF Path Data만 저장합니다. 유효하지 않은 아이콘 내용은 지워지고 테마가 적용된 오류 대화상자로 알립니다. 아이콘을 지정하지 않을 때는 빈 값도 유효합니다.

PluginConfigSchemaOnSaveOnRollback 생명주기 델리게이트를 지원합니다. OnSave는 사용자가 확인/적용을 눌러 변경 사항을 커밋할 때 실행되고, OnRollback은 취소하거나 되돌릴 때 상태를 복원합니다.

지역화된 선택 항목 레이블

안정적인 설정 값을 유지하면서 지역화된 레이블을 표시해야 하는 선택 항목에는 ChoiceOptions를 사용합니다. PluginConfigChoice.Value는 플러그인 설정에 저장되고 LabelKey는 화면에 표시할 텍스트로 해석됩니다. 저장 값과 표시 텍스트가 같다면 기존 Choices 컬렉션을 사용하면 됩니다.

csharp
new PluginConfigField
{
    Key = "DisplayMode",
    FieldType = ConfigFieldType.Choice,
    DefaultValue = "FriendlyName",
    ChoiceOptions =
    [
        new PluginConfigChoice
        {
            Value = "FriendlyName",
            LabelKey = "DisplayMode_FriendlyName"
        }
    ]
}

5. 전체 검색 창 파일 결과 IFullSearchFileResultProvider

전체 검색 창에 실제 파일 또는 폴더 행을 추가해야 하는 플러그인은 IFullSearchFileResultProvider를 구현할 수 있습니다.

csharp
public interface IFullSearchFileResultProvider : IPluginComponent
{
    IReadOnlyList<InstantResultItem> GetFileResults(string query, int limit);
}

호스트는 전체 검색 창의 최종 렌더링 단계에서만 GetFileResults를 호출합니다. 현재 쿼리를 처리하지 않을 때는 빈 목록을 반환하세요. 반환하는 각 InstantResultItem은 실제로 존재하는 파일 또는 폴더를 나타내야 전체 검색 창의 경로, 크기, 유형 열을 의미 있게 표시할 수 있습니다. 이 구성 요소는 플러그인의 즉시 결과 제공자와 동일한 활성화/비활성화 스위치로 관리됩니다.

6. 사용자 설정 경로 확인 UserPathResolver

플러그인이 사용자가 입력했거나 설정에 저장된 경로를 받을 때는 파일 시스템 API를 호출하기 전에 Lertaro.PluginSdk.Helpers.UserPathResolver를 사용하여 환경 변수와 Windows 셸 가상 경로를 동일한 규칙으로 처리하세요.

csharp
string expanded = UserPathResolver.Expand(rawPath);
bool isVirtual = UserPathResolver.IsVirtualPath(expanded);
string resolved = UserPathResolver.Resolve(rawPath);

Expand는 앞뒤 공백을 제거하고 %USERPROFILE% 같은 환경 변수를 확장합니다. Resolve는 확장 후 shell:Downloads 또는 ::{CLSID} 같은 토큰을 가능한 경우 실제 경로로 확인합니다. shell:AppsFolder처럼 실제 경로가 없는 가상 폴더는 대신 정규 ::{CLSID} 이름으로 확인되므로 같은 폴더의 여러 표기가 서로 일치합니다. 그 결과는 여전히 가상 경로입니다. 셸이 전혀 해석할 수 없는 토큰만 변경하지 않고 반환됩니다. 파일 시스템 API에 전달하기 전에 IsVirtualPath로 결과를 확인하세요. 디렉터리 인덱싱 API는 실제 폴더로 확인되고 호스트 인덱스 대상인 경로만 열거할 수 있습니다.